Преглед на файлове

Feature #2044 upload svg-edit 2.5.1

Juan Carlos Raña преди 14 години
родител
ревизия
192d02a69c
променени са 100 файла, в които са добавени 7427 реда и са изтрити 0 реда
  1. 1774 0
      main/inc/lib/svg-edit/canvg/canvg.js
  2. 287 0
      main/inc/lib/svg-edit/canvg/rgbcolor.js
  3. 157 0
      main/inc/lib/svg-edit/embedapi.js
  4. 41 0
      main/inc/lib/svg-edit/extensions/closepath_icons.svg
  5. 298 0
      main/inc/lib/svg-edit/extensions/ext-arrows.js
  6. 92 0
      main/inc/lib/svg-edit/extensions/ext-closepath.js
  7. 579 0
      main/inc/lib/svg-edit/extensions/ext-connector.js
  8. 101 0
      main/inc/lib/svg-edit/extensions/ext-eyedropper.js
  9. 277 0
      main/inc/lib/svg-edit/extensions/ext-foreignobject.js
  10. 78 0
      main/inc/lib/svg-edit/extensions/ext-helloworld.js
  11. 572 0
      main/inc/lib/svg-edit/extensions/ext-markers.js
  12. 179 0
      main/inc/lib/svg-edit/extensions/ext-server_opensave.js
  13. 34 0
      main/inc/lib/svg-edit/extensions/eyedropper-icon.xml
  14. BIN
      main/inc/lib/svg-edit/extensions/eyedropper.png
  15. 31 0
      main/inc/lib/svg-edit/extensions/fileopen.php
  16. 44 0
      main/inc/lib/svg-edit/extensions/filesave.php
  17. 96 0
      main/inc/lib/svg-edit/extensions/foreignobject-icons.xml
  18. 21 0
      main/inc/lib/svg-edit/extensions/helloworld-icon.xml
  19. 115 0
      main/inc/lib/svg-edit/extensions/markers-icons.xml
  20. 61 0
      main/inc/lib/svg-edit/images/README.txt
  21. BIN
      main/inc/lib/svg-edit/images/align-bottom.png
  22. 277 0
      main/inc/lib/svg-edit/images/align-bottom.svg
  23. BIN
      main/inc/lib/svg-edit/images/align-center.png
  24. 252 0
      main/inc/lib/svg-edit/images/align-center.svg
  25. BIN
      main/inc/lib/svg-edit/images/align-left.png
  26. 235 0
      main/inc/lib/svg-edit/images/align-left.svg
  27. BIN
      main/inc/lib/svg-edit/images/align-middle.png
  28. 250 0
      main/inc/lib/svg-edit/images/align-middle.svg
  29. BIN
      main/inc/lib/svg-edit/images/align-right.png
  30. 233 0
      main/inc/lib/svg-edit/images/align-right.svg
  31. BIN
      main/inc/lib/svg-edit/images/align-top.png
  32. 233 0
      main/inc/lib/svg-edit/images/align-top.svg
  33. BIN
      main/inc/lib/svg-edit/images/bold.png
  34. BIN
      main/inc/lib/svg-edit/images/cancel.png
  35. BIN
      main/inc/lib/svg-edit/images/circle.png
  36. BIN
      main/inc/lib/svg-edit/images/clear.png
  37. BIN
      main/inc/lib/svg-edit/images/clone.png
  38. 29 0
      main/inc/lib/svg-edit/images/conn.svg
  39. BIN
      main/inc/lib/svg-edit/images/copy.png
  40. BIN
      main/inc/lib/svg-edit/images/cut.png
  41. BIN
      main/inc/lib/svg-edit/images/delete.png
  42. BIN
      main/inc/lib/svg-edit/images/document-properties.png
  43. BIN
      main/inc/lib/svg-edit/images/dropdown.gif
  44. BIN
      main/inc/lib/svg-edit/images/ellipse.png
  45. BIN
      main/inc/lib/svg-edit/images/eye.png
  46. BIN
      main/inc/lib/svg-edit/images/fhpath.png
  47. BIN
      main/inc/lib/svg-edit/images/flyouth.png
  48. BIN
      main/inc/lib/svg-edit/images/flyup.gif
  49. BIN
      main/inc/lib/svg-edit/images/freehand-circle.png
  50. BIN
      main/inc/lib/svg-edit/images/freehand-square.png
  51. BIN
      main/inc/lib/svg-edit/images/go-down.png
  52. BIN
      main/inc/lib/svg-edit/images/go-up.png
  53. BIN
      main/inc/lib/svg-edit/images/image.png
  54. BIN
      main/inc/lib/svg-edit/images/italic.png
  55. BIN
      main/inc/lib/svg-edit/images/line.png
  56. BIN
      main/inc/lib/svg-edit/images/link_controls.png
  57. BIN
      main/inc/lib/svg-edit/images/logo.png
  58. 18 0
      main/inc/lib/svg-edit/images/logo.svg
  59. BIN
      main/inc/lib/svg-edit/images/move_bottom.png
  60. BIN
      main/inc/lib/svg-edit/images/move_top.png
  61. BIN
      main/inc/lib/svg-edit/images/node_clone.png
  62. BIN
      main/inc/lib/svg-edit/images/node_delete.png
  63. BIN
      main/inc/lib/svg-edit/images/none.png
  64. BIN
      main/inc/lib/svg-edit/images/open.png
  65. BIN
      main/inc/lib/svg-edit/images/paste.png
  66. BIN
      main/inc/lib/svg-edit/images/path.png
  67. BIN
      main/inc/lib/svg-edit/images/polygon.png
  68. 219 0
      main/inc/lib/svg-edit/images/polygon.svg
  69. BIN
      main/inc/lib/svg-edit/images/rect.png
  70. BIN
      main/inc/lib/svg-edit/images/redo.png
  71. BIN
      main/inc/lib/svg-edit/images/reorient.png
  72. BIN
      main/inc/lib/svg-edit/images/rotate.png
  73. BIN
      main/inc/lib/svg-edit/images/save.png
  74. BIN
      main/inc/lib/svg-edit/images/select.png
  75. BIN
      main/inc/lib/svg-edit/images/select_node.png
  76. BIN
      main/inc/lib/svg-edit/images/sep.png
  77. BIN
      main/inc/lib/svg-edit/images/shape_group.png
  78. BIN
      main/inc/lib/svg-edit/images/shape_ungroup.png
  79. BIN
      main/inc/lib/svg-edit/images/source.png
  80. BIN
      main/inc/lib/svg-edit/images/spinbtn_updn_big.png
  81. BIN
      main/inc/lib/svg-edit/images/square.png
  82. 21 0
      main/inc/lib/svg-edit/images/svg_edit_icons.svg
  83. BIN
      main/inc/lib/svg-edit/images/svg_edit_icons.svgz
  84. BIN
      main/inc/lib/svg-edit/images/text.png
  85. 157 0
      main/inc/lib/svg-edit/images/text.svg
  86. BIN
      main/inc/lib/svg-edit/images/to_path.png
  87. BIN
      main/inc/lib/svg-edit/images/undo.png
  88. BIN
      main/inc/lib/svg-edit/images/view-refresh.png
  89. BIN
      main/inc/lib/svg-edit/images/wave.png
  90. BIN
      main/inc/lib/svg-edit/images/wireframe.png
  91. BIN
      main/inc/lib/svg-edit/images/zoom.png
  92. 202 0
      main/inc/lib/svg-edit/jgraduate/LICENSE
  93. 3 0
      main/inc/lib/svg-edit/jgraduate/README
  94. 191 0
      main/inc/lib/svg-edit/jgraduate/css/jPicker-1.0.12.css
  95. 270 0
      main/inc/lib/svg-edit/jgraduate/css/jgraduate.css
  96. BIN
      main/inc/lib/svg-edit/jgraduate/images/AlphaBar.png
  97. BIN
      main/inc/lib/svg-edit/jgraduate/images/Bars.png
  98. BIN
      main/inc/lib/svg-edit/jgraduate/images/Maps.png
  99. BIN
      main/inc/lib/svg-edit/jgraduate/images/NoColor.png
  100. BIN
      main/inc/lib/svg-edit/jgraduate/images/bar-opacity.png

+ 1774 - 0
main/inc/lib/svg-edit/canvg/canvg.js

@@ -0,0 +1,1774 @@
+/*
+ * canvg.js - Javascript SVG parser and renderer on Canvas
+ * MIT Licensed 
+ * Gabe Lerner (gabelerner@gmail.com)
+ * http://code.google.com/p/canvg/
+ *
+ * Requires: rgbcolor.js - http://www.phpied.com/rgb-color-parser-in-javascript/
+ */
+if(!window.console) {
+	window.console = {};
+	window.console.log = function(str) {};
+	window.console.dir = function(str) {};
+}
+(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) {
+		if (typeof target == 'string') {
+			target = document.getElementById(target);
+		}
+		
+		// reuse class per canvas
+		var svg;
+		if (target.svg == null) {
+			svg = build();
+			target.svg = svg;
+		}
+		else {
+			svg = target.svg;
+			svg.stop();
+		}
+		
+		var ctx = target.getContext('2d');
+		if (s.substr(0,1) == '<') {
+			// load from xml string
+			svg.loadXml(ctx, s);
+		}
+		else {
+			// load from url
+			svg.load(ctx, s);
+		}
+	}
+
+	function build() {
+		var svg = {};
+		
+		svg.FRAMERATE = 30;
+		
+		// globals
+		svg.init = function(ctx) {
+			svg.Definitions = {};
+			svg.Styles = {};
+			svg.Animations = [];
+			svg.ctx = ctx;
+			svg.ViewPort = new (function () {
+				this.viewPorts = [];
+				this.SetCurrent = function(width, height) { this.viewPorts.push({ width: width, height: height }); }
+				this.RemoveCurrent = function() { this.viewPorts.pop(); }
+				this.Current = function() { return this.viewPorts[this.viewPorts.length - 1]; }
+				this.width = function() { return this.Current().width; }
+				this.height = function() { return this.Current().height; }
+				this.ComputeSize = function(d) {
+					if (d != null && typeof(d) == 'number') return d;
+					if (d == 'x') return this.width();
+					if (d == 'y') return this.height();
+					return Math.sqrt(Math.pow(this.width(), 2) + Math.pow(this.height(), 2)) / Math.sqrt(2);			
+				}
+			});
+		}
+		svg.init();
+
+		// trim
+		svg.trim = function(s) { return s.replace(/^\s+|\s+$/g, ''); }
+		
+		// compress spaces
+		svg.compressSpaces = function(s) { return s.replace(/[\s\r\t\n]+/gm,' '); }
+		
+		// ajax
+		svg.ajax = function(url) {
+			var AJAX;
+			if(window.XMLHttpRequest){AJAX=new XMLHttpRequest();}
+			else{AJAX=new ActiveXObject('Microsoft.XMLHTTP');}
+			if(AJAX){
+			   AJAX.open('GET',url,false);
+			   AJAX.send(null);
+			   return AJAX.responseText;
+			}
+			return null;
+		} 
+		
+		// parse xml
+		svg.parseXml = function(xml) {
+			if (window.DOMParser)
+			{
+				var parser = new DOMParser();
+				return parser.parseFromString(xml, 'text/xml');
+			}
+			else 
+			{
+				xml = xml.replace(/<!DOCTYPE svg[^>]*>/, '');
+				var xmlDoc = new ActiveXObject('Microsoft.XMLDOM');
+				xmlDoc.async = 'false';
+				xmlDoc.loadXML(xml); 
+				return xmlDoc;
+			}		
+		}
+		
+		svg.Property = function(name, value) {
+			this.name = name;
+			this.value = value;
+			
+			this.hasValue = function() {
+				return (this.value != null && this.value != '');
+			}
+							
+			// return the numerical value of the property
+			this.numValue = function() {
+				if (!this.hasValue()) return 0;
+				
+				var n = parseFloat(this.value);
+				if ((this.value + '').match(/%$/)) {
+					n = n / 100.0;
+				}
+				return n;
+			}
+			
+			this.valueOrDefault = function(def) {
+				if (this.hasValue()) return this.value;
+				return def;
+			}
+			
+			this.numValueOrDefault = function(def) {
+				if (this.hasValue()) return this.numValue();
+				return def;
+			}
+			
+			/* EXTENSIONS */
+			var that = this;
+			
+			// color extensions
+			this.Color = {
+				// augment the current color value with the opacity
+				addOpacity: function(opacity) {
+					var newValue = that.value;
+					if (opacity != null && opacity != '') {
+						var color = new RGBColor(that.value);
+						if (color.ok) {
+							newValue = 'rgba(' + color.r + ', ' + color.g + ', ' + color.b + ', ' + opacity + ')';
+						}
+					}
+					return new svg.Property(that.name, newValue);
+				}
+			}
+			
+			// definition extensions
+			this.Definition = {
+				// get the definition from the definitions table
+				getDefinition: function() {
+					var name = that.value.replace(/^(url\()?#([^\)]+)\)?$/, '$2');
+					return svg.Definitions[name];
+				},
+				
+				isUrl: function() {
+					return that.value.indexOf('url(') == 0
+				},
+				
+				getFillStyle: function(e) {
+					var def = this.getDefinition();
+					
+					// gradient
+					if (def != null && def.createGradient) {
+						return def.createGradient(svg.ctx, e);
+					}
+					
+					// pattern
+					if (def != null && def.createPattern) {
+						return def.createPattern(svg.ctx, e);
+					}
+					
+					return null;
+				}
+			}
+			
+			// length extensions
+			this.Length = {
+				DPI: function(viewPort) {
+					return 96.0; // TODO: compute?
+				},
+				
+				EM: function(viewPort) {
+					var em = 12;
+					
+					var fontSize = new svg.Property('fontSize', svg.Font.Parse(svg.ctx.font).fontSize);
+					if (fontSize.hasValue()) em = fontSize.Length.toPixels(viewPort);
+					
+					return em;
+				},
+			
+				// get the length as pixels
+				toPixels: function(viewPort) {
+					if (!that.hasValue()) return 0;
+					var s = that.value+'';
+					if (s.match(/em$/)) return that.numValue() * this.EM(viewPort);
+					if (s.match(/ex$/)) return that.numValue() * this.EM(viewPort) / 2.0;
+					if (s.match(/px$/)) return that.numValue();
+					if (s.match(/pt$/)) return that.numValue() * 1.25;
+					if (s.match(/pc$/)) return that.numValue() * 15;
+					if (s.match(/cm$/)) return that.numValue() * this.DPI(viewPort) / 2.54;
+					if (s.match(/mm$/)) return that.numValue() * this.DPI(viewPort) / 25.4;
+					if (s.match(/in$/)) return that.numValue() * this.DPI(viewPort);
+					if (s.match(/%$/)) return that.numValue() * svg.ViewPort.ComputeSize(viewPort);
+					return that.numValue();
+				}
+			}
+			
+			// time extensions
+			this.Time = {
+				// get the time as milliseconds
+				toMilliseconds: function() {
+					if (!that.hasValue()) return 0;
+					var s = that.value+'';
+					if (s.match(/s$/)) return that.numValue() * 1000;
+					if (s.match(/ms$/)) return that.numValue();
+					return that.numValue();
+				}
+			}
+			
+			// angle extensions
+			this.Angle = {
+				// get the angle as radians
+				toRadians: function() {
+					if (!that.hasValue()) return 0;
+					var s = that.value+'';
+					if (s.match(/deg$/)) return that.numValue() * (Math.PI / 180.0);
+					if (s.match(/grad$/)) return that.numValue() * (Math.PI / 200.0);
+					if (s.match(/rad$/)) return that.numValue();
+					return that.numValue() * (Math.PI / 180.0);
+				}
+			}
+		}
+		
+		// fonts
+		svg.Font = new (function() {
+			this.Styles = ['normal','italic','oblique','inherit'];
+			this.Variants = ['normal','small-caps','inherit'];
+			this.Weights = ['normal','bold','bolder','lighter','100','200','300','400','500','600','700','800','900','inherit'];
+			
+			this.CreateFont = function(fontStyle, fontVariant, fontWeight, fontSize, fontFamily, inherit) { 
+				var f = inherit != null ? this.Parse(inherit) : this.CreateFont('', '', '', '', '', svg.ctx.font);
+				return { 
+					fontFamily: fontFamily || f.fontFamily, 
+					fontSize: fontSize || f.fontSize, 
+					fontStyle: fontStyle || f.fontStyle, 
+					fontWeight: fontWeight || f.fontWeight, 
+					fontVariant: fontVariant || f.fontVariant,
+					toString: function () { return [this.fontStyle, this.fontVariant, this.fontWeight, this.fontSize, this.fontFamily].join(' ') } 
+				} 
+			}
+			
+			var that = this;
+			this.Parse = function(s) {
+				var f = {};
+				var d = svg.trim(svg.compressSpaces(s || '')).split(' ');
+				var set = { fontSize: false, fontStyle: false, fontWeight: false, fontVariant: false }
+				var ff = '';
+				for (var i=0; i<d.length; i++) {
+					if (!set.fontStyle && that.Styles.indexOf(d[i]) != -1) { if (d[i] != 'inherit') f.fontStyle = d[i]; set.fontStyle = true; }
+					else if (!set.fontVariant && that.Variants.indexOf(d[i]) != -1) { if (d[i] != 'inherit') f.fontVariant = d[i]; set.fontStyle = set.fontVariant = true;	}
+					else if (!set.fontWeight && that.Weights.indexOf(d[i]) != -1) {	if (d[i] != 'inherit') f.fontWeight = d[i]; set.fontStyle = set.fontVariant = set.fontWeight = true; }
+					else if (!set.fontSize) { if (d[i] != 'inherit') f.fontSize = d[i].split('/')[0]; set.fontStyle = set.fontVariant = set.fontWeight = set.fontSize = true; }
+					else { if (d[i] != 'inherit') ff += d[i]; }
+				} if (ff != '') f.fontFamily = ff;
+				return f;
+			}
+		});
+		
+		// points and paths
+		svg.ToNumberArray = function(s) {
+			var a = svg.trim(svg.compressSpaces((s || '').replace(/,/g, ' '))).split(' ');
+			for (var i=0; i<a.length; i++) {
+				a[i] = parseFloat(a[i]);
+			}
+			return a;
+		}		
+		svg.Point = function(x, y) {
+			this.x = x;
+			this.y = y;
+			
+			this.angleTo = function(p) {
+				return Math.atan2(p.y - this.y, p.x - this.x);
+			}
+		}
+		svg.CreatePoint = function(s) {
+			var a = svg.ToNumberArray(s);
+			return new svg.Point(a[0], a[1]);
+		}
+		svg.CreatePath = function(s) {
+			var a = svg.ToNumberArray(s);
+			var path = [];
+			for (var i=0; i<a.length; i+=2) {
+				path.push(new svg.Point(a[i], a[i+1]));
+			}
+			return path;
+		}
+		
+		// bounding box
+		svg.BoundingBox = function(x1, y1, x2, y2) { // pass in initial points if you want
+			this.x1 = Number.NaN;
+			this.y1 = Number.NaN;
+			this.x2 = Number.NaN;
+			this.y2 = Number.NaN;
+			
+			this.x = function() { return this.x1; }
+			this.y = function() { return this.y1; }
+			this.width = function() { return this.x2 - this.x1; }
+			this.height = function() { return this.y2 - this.y1; }
+			
+			this.addPoint = function(x, y) {	
+				if (x != null) {
+					if (isNaN(this.x1) || isNaN(this.x2)) {
+						this.x1 = x;
+						this.x2 = x;
+					}
+					if (x < this.x1) this.x1 = x;
+					if (x > this.x2) this.x2 = x;
+				}
+			
+				if (y != null) {
+					if (isNaN(this.y1) || isNaN(this.y2)) {
+						this.y1 = y;
+						this.y2 = y;
+					}
+					if (y < this.y1) this.y1 = y;
+					if (y > this.y2) this.y2 = y;
+				}
+			}			
+			this.addX = function(x) { this.addPoint(x, null); }
+			this.addY = function(y) { this.addPoint(null, y); }
+			
+			this.addQuadraticCurve = function(p0x, p0y, p1x, p1y, p2x, p2y) {
+				var cp1x = p0x + 2/3 * (p1x - p0x); // CP1 = QP0 + 2/3 *(QP1-QP0)
+				var cp1y = p0y + 2/3 * (p1y - p0y); // CP1 = QP0 + 2/3 *(QP1-QP0)
+				var cp2x = cp1x + 1/3 * (p2x - p0x); // CP2 = CP1 + 1/3 *(QP2-QP0)
+				var cp2y = cp1y + 1/3 * (p2y - p0y); // CP2 = CP1 + 1/3 *(QP2-QP0)
+				this.addBezierCurve(p0x, p0y, cp1x, cp2x, cp1y,	cp2y, p2x, p2y);
+			}
+			
+			this.addBezierCurve = function(p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y) {
+				// from http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html
+				var p0 = [p0x, p0y], p1 = [p1x, p1y], p2 = [p2x, p2y], p3 = [p3x, p3y];
+				this.addPoint(p0[0], p0[1]);
+				this.addPoint(p3[0], p3[1]);
+				
+				for (i=0; i<=1; i++) {
+					var f = function(t) { 
+						return Math.pow(1-t, 3) * p0[i]
+						+ 3 * Math.pow(1-t, 2) * t * p1[i]
+						+ 3 * (1-t) * Math.pow(t, 2) * p2[i]
+						+ Math.pow(t, 3) * p3[i];
+					}
+					
+					var b = 6 * p0[i] - 12 * p1[i] + 6 * p2[i];
+					var a = -3 * p0[i] + 9 * p1[i] - 9 * p2[i] + 3 * p3[i];
+					var c = 3 * p1[i] - 3 * p0[i];
+					
+					if (a == 0) {
+						if (b == 0) continue;
+						var t = -c / b;
+						if (0 < t && t < 1) {
+							if (i == 0) this.addX(f(t));
+							if (i == 1) this.addY(f(t));
+						}
+						continue;
+					}
+					
+					var b2ac = Math.pow(b, 2) - 4 * c * a;
+					if (b2ac < 0) continue;
+					var t1 = (-b + Math.sqrt(b2ac)) / (2 * a);
+					if (0 < t1 && t1 < 1) {
+						if (i == 0) this.addX(f(t1));
+						if (i == 1) this.addY(f(t1));
+					}
+					var t2 = (-b - Math.sqrt(b2ac)) / (2 * a);
+					if (0 < t2 && t2 < 1) {
+						if (i == 0) this.addX(f(t2));
+						if (i == 1) this.addY(f(t2));
+					}
+				}
+			}
+			
+			this.addPoint(x1, y1);
+			this.addPoint(x2, y2);
+		}
+		
+		// transforms
+		svg.Transform = function(v) {	
+			var that = this;
+			this.Type = {}
+		
+			// translate
+			this.Type.translate = function(s) {
+				this.p = svg.CreatePoint(s);			
+				this.apply = function(ctx) {
+					ctx.translate(this.p.x || 0.0, this.p.y || 0.0);
+				}
+			}
+			
+			// rotate
+			this.Type.rotate = function(s) {
+				var a = svg.ToNumberArray(s);
+				this.angle = new svg.Property('angle', a[0]);
+				this.cx = a[1] || 0;
+				this.cy = a[2] || 0;
+				this.apply = function(ctx) {
+					ctx.translate(this.cx, this.cy);
+					ctx.rotate(this.angle.Angle.toRadians());
+					ctx.translate(-this.cx, -this.cy);
+				}
+			}
+			
+			this.Type.scale = function(s) {
+				this.p = svg.CreatePoint(s);
+				this.apply = function(ctx) {
+					ctx.scale(this.p.x || 1.0, this.p.y || this.p.x || 1.0);
+				}
+			}
+			
+			this.Type.matrix = function(s) {
+				this.m = svg.ToNumberArray(s);
+				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.Type.SkewBase = function(s) {
+				this.base = that.Type.matrix;
+				this.base(s);
+				this.angle = new svg.Property('angle', s);
+			}
+			this.Type.SkewBase.prototype = new this.Type.matrix;
+			
+			this.Type.skewX = function(s) {
+				this.base = that.Type.SkewBase;
+				this.base(s);
+				this.m = [1, 0, Math.tan(this.angle.Angle.toRadians()), 1, 0, 0];
+			}
+			this.Type.skewX.prototype = new this.Type.SkewBase;
+			
+			this.Type.skewY = function(s) {
+				this.base = that.Type.SkewBase;
+				this.base(s);
+				this.m = [1, Math.tan(this.angle.Angle.toRadians()), 0, 1, 0, 0];
+			}
+			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);
+				}
+			}
+			
+			var data = v.split(/\s(?=[a-z])/);
+			for (var i=0; i<data.length; i++) {
+				var type = data[i].split('(')[0];
+				var s = data[i].split('(')[1].replace(')','');
+				var transform = eval('new this.Type.' + type + '(s)');
+				this.transforms.push(transform);
+			}
+		}
+		
+		// elements
+		svg.Element = {}
+		
+		svg.Element.ElementBase = function(node) {	
+			this.attributes = {};
+			this.styles = {};
+			this.children = [];
+			
+			// get or create attribute
+			this.attribute = function(name, createIfNotExists) {
+				var a = this.attributes[name];
+				if (a != null) return a;
+							
+				a = new svg.Property(name, '');
+				if (createIfNotExists == true) this.attributes[name] = a;
+				return a;
+			}
+			
+			// get or create style
+			this.style = function(name, createIfNotExists) {
+				var s = this.styles[name];
+				if (s != null) return s;
+				
+				var a = this.attribute(name);
+				if (a != null && a.hasValue()) {
+					return a;
+				}
+					
+				s = new svg.Property(name, '');
+				if (createIfNotExists == true) this.styles[name] = s;
+				return s;
+			}
+			
+			// base render
+			this.render = function(ctx) {
+				ctx.save();
+				this.setContext(ctx);
+				this.renderChildren(ctx);
+				this.clearContext(ctx);
+				ctx.restore();
+			}
+			
+			// base set context
+			this.setContext = function(ctx) {
+				// OVERRIDE ME!
+			}
+			
+			// base clear context
+			this.clearContext = function(ctx) {
+				// OVERRIDE ME!
+			}			
+			
+			// base render children
+			this.renderChildren = function(ctx) {
+				for (var i=0; i<this.children.length; i++) {
+					this.children[i].render(ctx);
+				}
+			}
+			
+			this.addChild = function(childNode, create) {
+				var child = childNode;
+				if (create) child = svg.CreateElement(childNode);
+				child.parent = this;
+				this.children.push(child);			
+			}
+				
+			if (node != null && node.nodeType == 1) { //ELEMENT_NODE
+				// add children
+				for (var i=0; i<node.childNodes.length; i++) {
+					var childNode = node.childNodes[i];
+					if (childNode.nodeType == 1) this.addChild(childNode, true); //ELEMENT_NODE
+				}
+				
+				// add attributes
+				for (var i=0; i<node.attributes.length; i++) {
+					var attribute = node.attributes[i];
+					this.attributes[attribute.nodeName] = new svg.Property(attribute.nodeName, attribute.nodeValue);
+				}
+										
+				// add tag styles
+				var styles = svg.Styles[this.type];
+				if (styles != null) {
+					for (var name in styles) {
+						this.styles[name] = styles[name];
+					}
+				}					
+				
+				// add class styles
+				if (this.attribute('class').hasValue()) {
+					var classes = svg.compressSpaces(this.attribute('class').value).split(' ');
+					for (var j=0; j<classes.length; j++) {
+						styles = svg.Styles['.'+classes[j]];
+						if (styles != null) {
+							for (var name in styles) {
+								this.styles[name] = styles[name];
+							}
+						}
+					}
+				}
+				
+				// add inline styles
+				if (this.attribute('style').hasValue()) {
+					var styles = this.attribute('style').value.split(';');
+					for (var i=0; i<styles.length; i++) {
+						if (svg.trim(styles[i]) != '') {
+							var style = styles[i].split(':');
+							var name = svg.trim(style[0]);
+							var value = svg.trim(style[1]);
+							this.styles[name] = new svg.Property(name, value);
+						}
+					}
+				}
+				
+				// set id
+				if (this.attribute('id').hasValue()) svg.Definitions[this.attribute('id').value] = this;				
+			}
+		}
+		
+		svg.Element.RenderedElementBase = function(node) {
+			this.base = svg.Element.ElementBase;
+			this.base(node);
+			
+			this.setContext = function(ctx) {
+				// fill
+				if (this.style('fill').Definition.isUrl()) {
+					var fs = this.style('fill').Definition.getFillStyle(this);
+					if (fs != null) ctx.fillStyle = fs;
+				}
+				else if (this.style('fill').hasValue()) {
+					var fillStyle = this.style('fill');
+					if (this.style('fill-opacity').hasValue()) fillStyle = fillStyle.Color.addOpacity(this.style('fill-opacity').value);
+					ctx.fillStyle = (fillStyle.value == 'none' ? 'rgba(0,0,0,0)' : fillStyle.value);
+				}
+									
+				// stroke
+				if (this.style('stroke').Definition.isUrl()) {
+					var fs = this.style('stroke').Definition.getFillStyle(this);
+					if (fs != null) ctx.strokeStyle = fs;
+				}
+				else if (this.style('stroke').hasValue()) {
+					var strokeStyle = this.style('stroke');
+					if (this.style('stroke-opacity').hasValue()) strokeStyle = strokeStyle.Color.addOpacity(this.style('stroke-opacity').value);
+					ctx.strokeStyle = (strokeStyle.value == 'none' ? 'rgba(0,0,0,0)' : strokeStyle.value);
+				}
+				if (this.style('stroke-width').hasValue()) ctx.lineWidth = this.style('stroke-width').Length.toPixels();
+				if (this.style('stroke-linecap').hasValue()) ctx.lineCap = this.style('stroke-linecap').value;
+				if (this.style('stroke-linejoin').hasValue()) ctx.lineJoin = this.style('stroke-linejoin').value;
+				if (this.style('stroke-miterlimit').hasValue()) ctx.miterLimit = this.style('stroke-miterlimit').value;
+
+				// font
+				if (typeof(ctx.font) != 'undefined') {
+					ctx.font = svg.Font.CreateFont( 
+						this.style('font-style').value, 
+						this.style('font-variant').value, 
+						this.style('font-weight').value, 
+						this.style('font-size').hasValue() ? this.style('font-size').Length.toPixels() + 'px' : '', 
+						this.style('font-family').value).toString();
+				}
+				
+				// transform
+				if (this.attribute('transform').hasValue()) { 
+					var transform = new svg.Transform(this.attribute('transform').value);
+					transform.apply(ctx);
+				}
+				
+				// clip
+				if (this.attribute('clip-path').hasValue()) {
+					var clip = this.attribute('clip-path').Definition.getDefinition();
+					if (clip != null) clip.apply(ctx);
+				}
+				
+				// opacity
+				if (this.style('opacity').hasValue()) {
+					ctx.globalAlpha = this.style('opacity').numValue();
+				}
+			}		
+		}
+		svg.Element.RenderedElementBase.prototype = new svg.Element.ElementBase;
+		
+		svg.Element.PathElementBase = function(node) {
+			this.base = svg.Element.RenderedElementBase;
+			this.base(node);
+			
+			this.path = function(ctx) {
+				if (ctx != null) ctx.beginPath();
+				return new svg.BoundingBox();
+			}
+			
+			this.renderChildren = function(ctx) {
+				this.path(ctx);
+				if (ctx.fillStyle != '') ctx.fill();
+				if (ctx.strokeStyle != '') ctx.stroke();
+				
+				var markers = this.getMarkers();
+				if (markers != null) {
+					if (this.attribute('marker-start').Definition.isUrl()) {
+						var marker = this.attribute('marker-start').Definition.getDefinition();
+						marker.render(ctx, markers[0][0], markers[0][1]);
+					}
+					if (this.attribute('marker-mid').Definition.isUrl()) {
+						var marker = this.attribute('marker-mid').Definition.getDefinition();
+						for (var i=1;i<markers.length-1;i++) {
+							marker.render(ctx, markers[i][0], markers[i][1]);
+						}
+					}
+					if (this.attribute('marker-end').Definition.isUrl()) {
+						var marker = this.attribute('marker-end').Definition.getDefinition();
+						marker.render(ctx, markers[markers.length-1][0], markers[markers.length-1][1]);
+					}
+				}					
+			}
+			
+			this.getBoundingBox = function() {
+				return this.path();
+			}
+			
+			this.getMarkers = function() {
+				return null;
+			}
+		}
+		svg.Element.PathElementBase.prototype = new svg.Element.RenderedElementBase;
+		
+		// svg element
+		svg.Element.svg = function(node) {
+			this.base = svg.Element.RenderedElementBase;
+			this.base(node);
+			
+			this.baseClearContext = this.clearContext;
+			this.clearContext = function(ctx) {
+				this.baseClearContext(ctx);
+				svg.ViewPort.RemoveCurrent();
+			}
+			
+			this.baseSetContext = this.setContext;
+			this.setContext = function(ctx) {
+				this.baseSetContext(ctx);
+				
+				// create new view port
+				if (this.attribute('x').hasValue() && this.attribute('y').hasValue()) {
+					ctx.translate(this.attribute('x').Length.toPixels('x'), this.attribute('y').Length.toPixels('y'));
+				}
+				
+				var width = svg.ViewPort.width();
+				var height = svg.ViewPort.height();
+				if (this.attribute('width').hasValue() && this.attribute('height').hasValue()) {
+					width = this.attribute('width').Length.toPixels('x');
+					height = this.attribute('height').Length.toPixels('y');
+					
+					var x = 0;
+					var y = 0;
+					if (this.attribute('refX').hasValue() && this.attribute('refY').hasValue()) {
+						x = -this.attribute('refX').Length.toPixels('x');
+						y = -this.attribute('refY').Length.toPixels('y');
+					}
+					
+					ctx.beginPath();
+					ctx.moveTo(x, y);
+					ctx.lineTo(width, y);
+					ctx.lineTo(width, height);
+					ctx.lineTo(x, height);
+					ctx.closePath();
+					ctx.clip();
+				}
+				svg.ViewPort.SetCurrent(width, height);	
+						
+				// viewbox
+				if (this.attribute('viewBox').hasValue()) {				
+					var viewBox = svg.ToNumberArray(this.attribute('viewBox').value);
+					var minX = viewBox[0];
+					var minY = viewBox[1];
+					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.ViewPort.RemoveCurrent();	
+					svg.ViewPort.SetCurrent(viewBox[2], viewBox[3]);						
+				}				
+				
+				// initial values
+				ctx.strokeStyle = 'rgba(0,0,0,0)';
+				ctx.lineCap = 'butt';
+				ctx.lineJoin = 'miter';
+				ctx.miterLimit = 4;
+			}
+		}
+		svg.Element.svg.prototype = new svg.Element.RenderedElementBase;
+
+		// rect element
+		svg.Element.rect = function(node) {
+			this.base = svg.Element.PathElementBase;
+			this.base(node);
+			
+			this.path = 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');
+				var rx = this.attribute('rx').Length.toPixels('x');
+				var ry = this.attribute('ry').Length.toPixels('y');
+				if (this.attribute('rx').hasValue() && !this.attribute('ry').hasValue()) ry = rx;
+				if (this.attribute('ry').hasValue() && !this.attribute('rx').hasValue()) rx = ry;
+				
+				if (ctx != null) {
+					ctx.beginPath();
+					ctx.moveTo(x + rx, y);
+					ctx.lineTo(x + width - rx, y);
+					ctx.quadraticCurveTo(x + width, y, x + width, y + ry)
+					ctx.lineTo(x + width, y + height - ry);
+					ctx.quadraticCurveTo(x + width, y + height, x + width - rx, y + height)
+					ctx.lineTo(x + rx, y + height);
+					ctx.quadraticCurveTo(x, y + height, x, y + height - ry)
+					ctx.lineTo(x, y + ry);
+					ctx.quadraticCurveTo(x, y, x + rx, y)
+					ctx.closePath();
+				}
+				
+				return new svg.BoundingBox(x, y, x + width, y + height);
+			}
+		}
+		svg.Element.rect.prototype = new svg.Element.PathElementBase;
+		
+		// circle element
+		svg.Element.circle = function(node) {
+			this.base = svg.Element.PathElementBase;
+			this.base(node);
+			
+			this.path = function(ctx) {
+				var cx = this.attribute('cx').Length.toPixels('x');
+				var cy = this.attribute('cy').Length.toPixels('y');
+				var r = this.attribute('r').Length.toPixels();
+			
+				if (ctx != null) {
+					ctx.beginPath();
+					ctx.arc(cx, cy, r, 0, Math.PI * 2, true); 
+					ctx.closePath();
+				}
+				
+				return new svg.BoundingBox(cx - r, cy - r, cx + r, cy + r);
+			}
+		}
+		svg.Element.circle.prototype = new svg.Element.PathElementBase;	
+
+		// ellipse element
+		svg.Element.ellipse = function(node) {
+			this.base = svg.Element.PathElementBase;
+			this.base(node);
+			
+			this.path = function(ctx) {
+				var KAPPA = 4 * ((Math.sqrt(2) - 1) / 3);
+				var rx = this.attribute('rx').Length.toPixels('x');
+				var ry = this.attribute('ry').Length.toPixels('y');
+				var cx = this.attribute('cx').Length.toPixels('x');
+				var cy = this.attribute('cy').Length.toPixels('y');
+				
+				if (ctx != null) {
+					ctx.beginPath();
+					ctx.moveTo(cx, cy - ry);
+					ctx.bezierCurveTo(cx + (KAPPA * rx), cy - ry,  cx + rx, cy - (KAPPA * ry), cx + rx, cy);
+					ctx.bezierCurveTo(cx + rx, cy + (KAPPA * ry), cx + (KAPPA * rx), cy + ry, cx, cy + ry);
+					ctx.bezierCurveTo(cx - (KAPPA * rx), cy + ry, cx - rx, cy + (KAPPA * ry), cx - rx, cy);
+					ctx.bezierCurveTo(cx - rx, cy - (KAPPA * ry), cx - (KAPPA * rx), cy - ry, cx, cy - ry);
+					ctx.closePath();
+				}
+				
+				return new svg.BoundingBox(cx - rx, cy - ry, cx + rx, cy + ry);
+			}
+		}
+		svg.Element.ellipse.prototype = new svg.Element.PathElementBase;			
+		
+		// line element
+		svg.Element.line = function(node) {
+			this.base = svg.Element.PathElementBase;
+			this.base(node);
+			
+			this.getPoints = function() {
+				return [
+					new svg.Point(this.attribute('x1').Length.toPixels('x'), this.attribute('y1').Length.toPixels('y')),
+					new svg.Point(this.attribute('x2').Length.toPixels('x'), this.attribute('y2').Length.toPixels('y'))];
+			}
+								
+			this.path = function(ctx) {
+				var points = this.getPoints();
+				
+				if (ctx != null) {
+					ctx.beginPath();
+					ctx.moveTo(points[0].x, points[0].y);
+					ctx.lineTo(points[1].x, points[1].y);
+				}
+				
+				return new svg.BoundingBox(points[0].x, points[0].y, points[1].x, points[1].y);
+			}
+			
+			this.getMarkers = function() {
+				var points = this.getPoints();	
+				var a = points[0].angleTo(points[1]);
+				return [[points[0], a], [points[1], a]];
+			}
+		}
+		svg.Element.line.prototype = new svg.Element.PathElementBase;		
+				
+		// polyline element
+		svg.Element.polyline = function(node) {
+			this.base = svg.Element.PathElementBase;
+			this.base(node);
+			
+			this.points = svg.CreatePath(this.attribute('points').value);
+			this.path = function(ctx) {
+				var bb = new svg.BoundingBox(this.points[0].x, this.points[0].y);
+				if (ctx != null) {
+					ctx.beginPath();
+					ctx.moveTo(this.points[0].x, this.points[0].y);
+				}
+				for (var i=1; i<this.points.length; i++) {
+					bb.addPoint(this.points[i].x, this.points[i].y);
+					if (ctx != null) ctx.lineTo(this.points[i].x, this.points[i].y);
+				}
+				return bb;
+			}
+			
+			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])]);
+				}
+				markers.push([this.points[this.points.length-1], markers[markers.length-1][1]]);
+				return markers;
+			}			
+		}
+		svg.Element.polyline.prototype = new svg.Element.PathElementBase;				
+				
+		// polygon element
+		svg.Element.polygon = function(node) {
+			this.base = svg.Element.polyline;
+			this.base(node);
+			
+			this.basePath = this.path;
+			this.path = function(ctx) {
+				var bb = this.basePath(ctx);
+				if (ctx != null) {
+					ctx.lineTo(this.points[0].x, this.points[0].y);
+					ctx.closePath();
+				}
+				return bb;
+			}
+		}
+		svg.Element.polygon.prototype = new svg.Element.polyline;
+
+		// path element
+		svg.Element.path = function(node) {
+			this.base = svg.Element.PathElementBase;
+			this.base(node);
+					
+			var d = this.attribute('d').value;
+			// TODO: floating points, convert to real lexer based on http://www.w3.org/TR/SVG11/paths.html#PathDataBNF
+			d = d.replace(/,/gm,' '); // get rid of all commas
+			d = d.replace(/([A-Za-z])([A-Za-z])/gm,'$1 $2'); // separate commands from commands
+			d = d.replace(/([A-Za-z])([A-Za-z])/gm,'$1 $2'); // separate commands from commands
+			d = d.replace(/([A-Za-z])([^\s])/gm,'$1 $2'); // separate commands from points
+			d = d.replace(/([^\s])([A-Za-z])/gm,'$1 $2'); // separate commands from points
+			d = d.replace(/([0-9])([+\-])/gm,'$1 $2'); // separate digits when no comma
+			d = d.replace(/(\.[0-9]*)(\.)/gm,'$1 $2'); // separate digits when no comma
+			d = d.replace(/([Aa](\s+[0-9]+){3})\s+([01])\s*([01])/gm,'$1 $3 $4 '); // shorthand elliptical arc path syntax
+			d = svg.compressSpaces(d); // compress multiple spaces
+			d = svg.trim(d);
+			this.PathParser = new (function(d) {
+				this.tokens = d.split(' ');
+				
+				this.reset = function() {
+					this.i = -1;
+					this.command = '';
+					this.control = new svg.Point(0, 0);
+					this.current = new svg.Point(0, 0);
+					this.points = [];
+					this.angles = [];
+				}
+								
+				this.isEnd = function() {
+					return this.i == this.tokens.length - 1;
+				}
+				
+				this.isCommandOrEnd = function() {
+					if (this.isEnd()) return true;
+					return this.tokens[this.i + 1].match(/[A-Za-z]/) != null;
+				}
+				
+				this.isRelativeCommand = function() {
+					return this.command == this.command.toLowerCase();
+				}
+				
+				this.getToken = function() {
+					this.i = this.i + 1;
+					return this.tokens[this.i];
+				}
+				
+				this.getScalar = function() {
+					return parseFloat(this.getToken());
+				}
+				
+				this.nextCommand = function() {
+					this.command = this.getToken();
+				}				
+				
+				this.getPoint = function() {
+					var p = new svg.Point(this.getScalar(), this.getScalar());
+					return this.makeAbsolute(p);
+				}
+				
+				this.getAsControlPoint = function() {
+					var p = this.getPoint();
+					this.control = p;
+					return p;
+				}
+				
+				this.getAsCurrentPoint = function() {
+					var p = this.getPoint();
+					this.current = p;
+					return p;	
+				}
+				
+				this.getReflectedControlPoint = function() {
+					var p = new svg.Point(2 * this.current.x - this.control.x, 2 * this.current.y - this.control.y);					
+					return this.makeAbsolute(p);
+				}
+				
+				this.makeAbsolute = function(p) {
+					if (this.isRelativeCommand()) {
+						p.x = this.current.x + p.x;
+						p.y = this.current.y + p.y;
+					}
+					return p;
+				}
+				
+				this.addMarker = function(p, from) {
+					this.addMarkerAngle(p, from == null ? null : from.angleTo(p));
+				}
+				
+				this.addMarkerAngle = function(p, a) {
+					this.points.push(p);
+					this.angles.push(a);
+				}				
+				
+				this.getMarkerPoints = function() { return this.points; }
+				this.getMarkerAngles = function() {
+					for (var i=0; i<this.angles.length; i++) {
+						if (this.angles[i] == null) {
+							for (var j=i+1; j<this.angles.length; j++) {
+								if (this.angles[j] != null) {
+									this.angles[i] = this.angles[j];
+									break;
+								}
+							}
+						}
+					}
+					return this.angles;
+				}
+			})(d);
+			
+			this.path = function(ctx) {		
+				var pp = this.PathParser;
+				pp.reset();
+				
+				var bb = new svg.BoundingBox();
+				if (ctx != null) ctx.beginPath();
+				while (!pp.isEnd()) {
+					pp.nextCommand();
+					if (pp.command.toUpperCase() == 'M') {
+						var p = pp.getAsCurrentPoint();
+						pp.addMarker(p);
+						bb.addPoint(p.x, p.y);
+						if (ctx != null) ctx.moveTo(p.x, p.y);
+						while (!pp.isCommandOrEnd()) {
+							var p = pp.getAsCurrentPoint();
+							pp.addMarker(p);
+							bb.addPoint(p.x, p.y);
+							if (ctx != null) ctx.lineTo(p.x, p.y);
+						}
+					}
+					else if (pp.command.toUpperCase() == 'L') {
+						while (!pp.isCommandOrEnd()) {
+							var c = pp.current;
+							var p = pp.getAsCurrentPoint();
+							pp.addMarker(p, c);
+							bb.addPoint(p.x, p.y);
+							if (ctx != null) ctx.lineTo(p.x, p.y);
+						}
+					}
+					else if (pp.command.toUpperCase() == 'H') {
+						while (!pp.isCommandOrEnd()) {
+							var newP = new svg.Point((pp.isRelativeCommand() ? pp.current.x : 0) + pp.getScalar(), pp.current.y);
+							pp.addMarker(newP, pp.current);
+							pp.current = newP;
+							bb.addPoint(pp.current.x, pp.current.y);
+							if (ctx != null) ctx.lineTo(pp.current.x, pp.current.y);
+						}
+					}
+					else if (pp.command.toUpperCase() == 'V') {
+						while (!pp.isCommandOrEnd()) {
+							var newP = new svg.Point(pp.current.x, (pp.isRelativeCommand() ? pp.current.y : 0) + pp.getScalar());
+							pp.addMarker(newP, pp.current);
+							pp.current = newP;
+							bb.addPoint(pp.current.x, pp.current.y);
+							if (ctx != null) ctx.lineTo(pp.current.x, pp.current.y);
+						}
+					}
+					else if (pp.command.toUpperCase() == 'C') {
+						while (!pp.isCommandOrEnd()) {
+							var curr = pp.current;
+							var p1 = pp.getPoint();
+							var cntrl = pp.getAsControlPoint();
+							var cp = pp.getAsCurrentPoint();
+							pp.addMarker(cp, cntrl);
+							bb.addBezierCurve(curr.x, curr.y, p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
+							if (ctx != null) ctx.bezierCurveTo(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
+						}
+					}
+					else if (pp.command.toUpperCase() == 'S') {
+						while (!pp.isCommandOrEnd()) {
+							var curr = pp.current;
+							var p1 = pp.getReflectedControlPoint();
+							var cntrl = pp.getAsControlPoint();
+							var cp = pp.getAsCurrentPoint();
+							pp.addMarker(cp, cntrl);
+							bb.addBezierCurve(curr.x, curr.y, p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
+							if (ctx != null) ctx.bezierCurveTo(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
+						}				
+					}					
+					else if (pp.command.toUpperCase() == 'Q') {
+						while (!pp.isCommandOrEnd()) {
+							var curr = pp.current;
+							var cntrl = pp.getAsControlPoint();
+							var cp = pp.getAsCurrentPoint();
+							pp.addMarker(cp, cntrl);
+							bb.addQuadraticCurve(curr.x, curr.y, cntrl.x, cntrl.y, cp.x, cp.y);
+							if (ctx != null) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y);
+						}
+					}					
+					else if (pp.command.toUpperCase() == 'T') {
+						while (!pp.isCommandOrEnd()) {
+							var curr = pp.current;
+							var cntrl = pp.getReflectedControlPoint();
+							pp.control = cntrl;
+							var cp = pp.getAsCurrentPoint();
+							pp.addMarker(cp, cntrl);
+							bb.addQuadraticCurve(curr.x, curr.y, cntrl.x, cntrl.y, cp.x, cp.y);
+							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;
+							var rx = pp.getScalar();
+							var ry = pp.getScalar();
+							var xAxisRotation = pp.getScalar() * (Math.PI / 180.0);
+							var largeArcFlag = pp.getScalar();
+							var sweepFlag = pp.getScalar();
+							var cp = pp.getAsCurrentPoint();
+							
+							// Conversion from endpoint to center parameterization
+							// http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
+							// x1', y1'
+							var currp = new svg.Point(
+								Math.cos(xAxisRotation) * (curr.x - cp.x) / 2.0 + Math.sin(xAxisRotation) * (curr.y - cp.y) / 2.0,
+								-Math.sin(xAxisRotation) * (curr.x - cp.x) / 2.0 + Math.cos(xAxisRotation) * (curr.y - cp.y) / 2.0
+							);
+							// adjust radii
+							var l = Math.pow(currp.x,2)/Math.pow(rx,2)+Math.pow(currp.y,2)/Math.pow(ry,2);
+							if (l > 1) {
+								rx *= Math.sqrt(l);
+								ry *= Math.sqrt(l);
+							}
+							// cx', cy'
+							var s = (largeArcFlag == sweepFlag ? -1 : 1) * Math.sqrt(
+								((Math.pow(rx,2)*Math.pow(ry,2))-(Math.pow(rx,2)*Math.pow(currp.y,2))-(Math.pow(ry,2)*Math.pow(currp.x,2))) /
+								(Math.pow(rx,2)*Math.pow(currp.y,2)+Math.pow(ry,2)*Math.pow(currp.x,2))
+							);
+							if (isNaN(s)) s = 0;
+							var cpp = new svg.Point(s * rx * currp.y / ry, s * -ry * currp.x / rx);
+							// cx, cy
+							var centp = new svg.Point(
+								(curr.x + cp.x) / 2.0 + Math.cos(xAxisRotation) * cpp.x - Math.sin(xAxisRotation) * cpp.y,
+								(curr.y + cp.y) / 2.0 + Math.sin(xAxisRotation) * cpp.x + Math.cos(xAxisRotation) * cpp.y
+							);
+							// vector magnitude
+							var m = function(v) { return Math.sqrt(Math.pow(v[0],2) + Math.pow(v[1],2)); }
+							// ratio between two vectors
+							var r = function(u, v) { return (u[0]*v[0]+u[1]*v[1]) / (m(u)*m(v)) }
+							// angle between two vectors
+							var a = function(u, v) { return (u[0]*v[1] < u[1]*v[0] ? -1 : 1) * Math.acos(r(u,v)); }
+							// initial angle
+							var a1 = a([1,0], [(currp.x-cpp.x)/rx,(currp.y-cpp.y)/ry]);
+							// angle delta
+							var u = [(currp.x-cpp.x)/rx,(currp.y-cpp.y)/ry];
+							var v = [(-currp.x-cpp.x)/rx,(-currp.y-cpp.y)/ry];
+							var ad = a(u, v);
+							if (r(u,v) <= -1) ad = Math.PI;
+							if (r(u,v) >= 1) ad = 0;
+							
+							if (sweepFlag == 0 && ad > 0) ad = ad - 2 * Math.PI;
+							if (sweepFlag == 1 && ad < 0) ad = ad + 2 * Math.PI;
+							
+							// for markers
+							var halfWay = new svg.Point(
+								centp.x - rx * Math.cos((a1 + ad) / 2),
+								centp.y - ry * Math.sin((a1 + ad) / 2)
+							);
+							pp.addMarkerAngle(halfWay, (a1 + ad) / 2 + (sweepFlag == 0 ? 1 : -1) * Math.PI / 2);
+							pp.addMarkerAngle(cp, ad + (sweepFlag == 0 ? 1 : -1) * Math.PI / 2);
+														
+							bb.addPoint(cp.x, cp.y); // TODO: this is too naive, make it better
+							if (ctx != null) {
+								var r = rx > ry ? rx : ry;
+								var sx = rx > ry ? 1 : rx / ry;
+								var sy = rx > ry ? ry / rx : 1;
+							
+								ctx.translate(centp.x, centp.y);
+								ctx.rotate(xAxisRotation);
+								ctx.scale(sx, sy);
+								ctx.arc(0, 0, r, a1, a1 + ad, 1 - sweepFlag);
+								ctx.scale(1/sx, 1/sy);
+								ctx.rotate(-xAxisRotation);
+								ctx.translate(-centp.x, -centp.y);
+							}
+						}
+					}
+					else if (pp.command.toUpperCase() == 'Z') {
+						if (ctx != null) ctx.closePath();
+					}
+				}
+							
+				return bb;
+			}
+			
+			this.getMarkers = function() {
+				var points = this.PathParser.getMarkerPoints();
+				var angles = this.PathParser.getMarkerAngles();
+				
+				var markers = [];
+				for (var i=0; i<points.length; i++) {
+					markers.push([points[i], angles[i]]);
+				}
+				return markers;
+			}
+		}
+		svg.Element.path.prototype = new svg.Element.PathElementBase;
+		
+		// pattern element
+		svg.Element.pattern = function(node) {
+			this.base = svg.Element.ElementBase;
+			this.base(node);
+			
+			this.createPattern = function(ctx, element) {
+				// render me using a temporary svg element
+				var tempSvg = new svg.Element.svg();
+				tempSvg.attributes['viewBox'] = new svg.Property('viewBox', this.attribute('viewBox').value);
+				tempSvg.attributes['x'] = new svg.Property('x', this.attribute('x').value);
+				tempSvg.attributes['y'] = new svg.Property('y', this.attribute('y').value);
+				tempSvg.attributes['width'] = new svg.Property('width', this.attribute('width').value);
+				tempSvg.attributes['height'] = new svg.Property('height', this.attribute('height').value);
+				tempSvg.children = this.children;
+				
+				var c = document.createElement('canvas');
+				c.width = this.attribute('width').Length.toPixels();
+				c.height = this.attribute('height').Length.toPixels();
+				tempSvg.render(c.getContext('2d'));		
+				return ctx.createPattern(c, 'repeat');
+			}
+		}
+		svg.Element.pattern.prototype = new svg.Element.ElementBase;
+		
+		// marker element
+		svg.Element.marker = function(node) {
+			this.base = svg.Element.ElementBase;
+			this.base(node);
+			
+			this.baseRender = this.render;
+			this.render = function(ctx, point, angle) {
+				ctx.translate(point.x, point.y);
+				if (this.attribute('orient').valueOrDefault('auto') == 'auto') ctx.rotate(angle);
+				if (this.attribute('markerUnits').valueOrDefault('strokeWidth') == 'strokeWidth') ctx.scale(ctx.lineWidth, ctx.lineWidth);
+				ctx.save();
+							
+				// render me using a temporary svg element
+				var tempSvg = new svg.Element.svg();
+				tempSvg.attributes['viewBox'] = new svg.Property('viewBox', this.attribute('viewBox').value);
+				tempSvg.attributes['refX'] = new svg.Property('refX', this.attribute('refX').value);
+				tempSvg.attributes['refY'] = new svg.Property('refY', this.attribute('refY').value);
+				tempSvg.attributes['width'] = new svg.Property('width', this.attribute('markerWidth').value);
+				tempSvg.attributes['height'] = new svg.Property('height', this.attribute('markerHeight').value);
+				tempSvg.attributes['fill'] = new svg.Property('fill', this.attribute('fill').valueOrDefault('black'));
+				tempSvg.attributes['stroke'] = new svg.Property('stroke', this.attribute('stroke').valueOrDefault('none'));
+				tempSvg.children = this.children;
+				tempSvg.render(ctx);
+				
+				ctx.restore();
+				if (this.attribute('markerUnits').valueOrDefault('strokeWidth') == 'strokeWidth') ctx.scale(1/ctx.lineWidth, 1/ctx.lineWidth);
+				if (this.attribute('orient').valueOrDefault('auto') == 'auto') ctx.rotate(-angle);
+				ctx.translate(-point.x, -point.y);
+			}
+		}
+		svg.Element.marker.prototype = new svg.Element.ElementBase;
+		
+		// definitions element
+		svg.Element.defs = function(node) {
+			this.base = svg.Element.ElementBase;
+			this.base(node);			
+			
+			this.render = function(ctx) {
+				// NOOP
+			}
+		}
+		svg.Element.defs.prototype = new svg.Element.ElementBase;
+		
+		// base for gradients
+		svg.Element.GradientBase = function(node) {
+			this.base = svg.Element.ElementBase;
+			this.base(node);
+			
+			this.gradientUnits = this.attribute('gradientUnits').valueOrDefault('objectBoundingBox');
+			
+			this.stops = [];			
+			for (var i=0; i<this.children.length; i++) {
+				var child = this.children[i];
+				this.stops.push(child);
+			}	
+
+			this.getGradient = function() {
+				// OVERRIDE ME!
+			}			
+
+			this.createGradient = function(ctx, element) {
+				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);
+				}
+				return g;				
+			}
+		}
+		svg.Element.GradientBase.prototype = new svg.Element.ElementBase;
+		
+		// linear gradient element
+		svg.Element.linearGradient = function(node) {
+			this.base = svg.Element.GradientBase;
+			this.base(node);
+			
+			this.getGradient = function(ctx, element) {
+				var bb = element.getBoundingBox();
+				
+				var x1 = (this.gradientUnits == 'objectBoundingBox' 
+					? bb.x() + bb.width() * this.attribute('x1').numValue() 
+					: this.attribute('x1').Length.toPixels('x'));
+				var y1 = (this.gradientUnits == 'objectBoundingBox' 
+					? bb.y() + bb.height() * this.attribute('y1').numValue()
+					: this.attribute('y1').Length.toPixels('y'));
+				var x2 = (this.gradientUnits == 'objectBoundingBox' 
+					? bb.x() + bb.width() * this.attribute('x2').numValue()
+					: this.attribute('x2').Length.toPixels('x'));
+				var y2 = (this.gradientUnits == 'objectBoundingBox' 
+					? bb.y() + bb.height() * this.attribute('y2').numValue()
+					: this.attribute('y2').Length.toPixels('y'));
+				
+				return ctx.createLinearGradient(x1, y1, x2, y2);
+			}
+		}
+		svg.Element.linearGradient.prototype = new svg.Element.GradientBase;
+		
+		// radial gradient element
+		svg.Element.radialGradient = function(node) {
+			this.base = svg.Element.GradientBase;
+			this.base(node);
+			
+			this.getGradient = function(ctx, element) {
+				var bb = element.getBoundingBox();
+				
+				var cx = (this.gradientUnits == 'objectBoundingBox' 
+					? bb.x() + bb.width() * this.attribute('cx').numValue() 
+					: this.attribute('cx').Length.toPixels('x'));
+				var cy = (this.gradientUnits == 'objectBoundingBox' 
+					? bb.y() + bb.height() * this.attribute('cy').numValue() 
+					: this.attribute('cy').Length.toPixels('y'));
+				
+				var fx = cx;
+				var fy = cy;
+				if (this.attribute('fx').hasValue()) {
+					fx = (this.gradientUnits == 'objectBoundingBox' 
+					? bb.x() + bb.width() * this.attribute('fx').numValue() 
+					: this.attribute('fx').Length.toPixels('x'));
+				}
+				if (this.attribute('fy').hasValue()) {
+					fy = (this.gradientUnits == 'objectBoundingBox' 
+					? bb.y() + bb.height() * this.attribute('fy').numValue() 
+					: this.attribute('fy').Length.toPixels('y'));
+				}
+				
+				var r = (this.gradientUnits == 'objectBoundingBox' 
+					? (bb.width() + bb.height()) / 2.0 * this.attribute('r').numValue()
+					: this.attribute('r').Length.toPixels());
+				
+				return ctx.createRadialGradient(fx, fy, 0, cx, cy, r);
+			}
+		}
+		svg.Element.radialGradient.prototype = new svg.Element.GradientBase;
+		
+		// gradient stop element
+		svg.Element.stop = function(node) {
+			this.base = svg.Element.ElementBase;
+			this.base(node);
+			
+			this.offset = this.attribute('offset').numValue();
+			
+			var stopColor = this.style('stop-color');
+			if (this.style('stop-opacity').hasValue()) stopColor = stopColor.Color.addOpacity(this.style('stop-opacity').value);
+			this.color = stopColor.value;
+		}
+		svg.Element.stop.prototype = new svg.Element.ElementBase;
+		
+		// animation base element
+		svg.Element.AnimateBase = function(node) {
+			this.base = svg.Element.ElementBase;
+			this.base(node);
+			
+			svg.Animations.push(this);
+			
+			this.duration = 0.0;
+			this.begin = this.attribute('begin').Time.toMilliseconds();
+			this.maxDuration = this.begin + this.attribute('dur').Time.toMilliseconds();
+
+			this.calcValue = function() {
+				// OVERRIDE ME!
+				return '';
+			}
+			
+			this.update = function(delta) {			
+				// if we're past the end time
+				if (this.duration > this.maxDuration) {
+					// loop for indefinitely repeating animations
+					if (this.attribute('repeatCount').value == 'indefinite') {
+						this.duration = 0.0
+					}
+					else {
+						return false; // no updates made
+					}
+				}			
+				this.duration = this.duration + delta;
+			
+				// if we're past the begin time
+				var updated = false;
+				if (this.begin < this.duration) {
+					var newValue = this.calcValue(); // tween
+					var attributeType = this.attribute('attributeType').value;
+					var attributeName = this.attribute('attributeName').value;
+					
+					if (this.parent != null) {
+						if (attributeType == 'CSS') {
+							this.parent.style(attributeName, true).value = newValue;
+						}
+						else { // default or XML
+							if (this.attribute('type').hasValue()) {
+								// for transform, etc.
+								var type = this.attribute('type').value;
+								this.parent.attribute(attributeName, true).value = type + '(' + newValue + ')';
+							}
+							else {
+								this.parent.attribute(attributeName, true).value = newValue;
+							}
+						}
+						updated = true;
+					}
+				}
+				
+				return updated;
+			}
+			
+			// fraction of duration we've covered
+			this.progress = function() {
+				return ((this.duration - this.begin) / (this.maxDuration - this.begin));
+			}			
+		}
+		svg.Element.AnimateBase.prototype = new svg.Element.ElementBase;
+		
+		// animate element
+		svg.Element.animate = function(node) {
+			this.base = svg.Element.AnimateBase;
+			this.base(node);
+			
+			this.calcValue = function() {
+				var from = this.attribute('from').numValue();
+				var to = this.attribute('to').numValue();
+				
+				// tween value linearly
+				return from + (to - from) * this.progress(); 
+			};
+		}
+		svg.Element.animate.prototype = new svg.Element.AnimateBase;
+			
+		// animate color element
+		svg.Element.animateColor = function(node) {
+			this.base = svg.Element.AnimateBase;
+			this.base(node);
+
+			this.calcValue = function() {
+				var from = new RGBColor(this.attribute('from').value);
+				var to = new RGBColor(this.attribute('to').value);
+				
+				if (from.ok && to.ok) {
+					// tween color linearly
+					var r = from.r + (to.r - from.r) * this.progress();
+					var g = from.g + (to.g - from.g) * this.progress();
+					var b = from.b + (to.b - from.b) * this.progress();
+					return 'rgb('+parseInt(r,10)+','+parseInt(g,10)+','+parseInt(b,10)+')';
+				}
+				return this.attribute('from').value;
+			};
+		}
+		svg.Element.animateColor.prototype = new svg.Element.AnimateBase;
+		
+		// animate transform element
+		svg.Element.animateTransform = function(node) {
+			this.base = svg.Element.animate;
+			this.base(node);
+		}
+		svg.Element.animateTransform.prototype = new svg.Element.animate;
+		
+		// text element
+		svg.Element.text = function(node) {
+			this.base = svg.Element.RenderedElementBase;
+			this.base(node);
+			
+			if (node != null) {
+				// add children
+				this.children = [];
+				for (var i=0; i<node.childNodes.length; i++) {
+					var childNode = node.childNodes[i];
+					if (childNode.nodeType == 1) { // capture tspan and tref nodes
+						this.addChild(childNode, true);
+					}
+					else if (childNode.nodeType == 3) { // capture text
+						this.addChild(new svg.Element.tspan(childNode), false);
+					}
+				}
+			}
+			
+			this.baseSetContext = this.setContext;
+			this.setContext = function(ctx) {
+				this.baseSetContext(ctx);
+				if (this.attribute('text-anchor').hasValue()) {
+					var textAnchor = this.attribute('text-anchor').value;
+					ctx.textAlign = textAnchor == 'middle' ? 'center' : textAnchor;
+				}
+				if (this.attribute('alignment-baseline').hasValue()) ctx.textBaseline = this.attribute('alignment-baseline').value;
+			}
+			
+			this.renderChildren = function(ctx) {
+				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);
+				}
+			}
+		}
+		svg.Element.text.prototype = new svg.Element.RenderedElementBase;
+		
+		// text base
+		svg.Element.TextElementBase = function(node) {
+			this.base = svg.Element.RenderedElementBase;
+			this.base(node);
+			
+			this.renderChildren = function(ctx) {
+				ctx.fillText(svg.compressSpaces(this.getText()), this.x, this.y);
+			}
+			
+			this.getText = function() {
+				// OVERRIDE ME
+			}
+			
+			this.measureText = function(ctx) {
+				return ctx.measureText(svg.compressSpaces(this.getText())).width;
+			}
+		}
+		svg.Element.TextElementBase.prototype = new svg.Element.RenderedElementBase;
+		
+		// tspan 
+		svg.Element.tspan = function(node) {
+			this.base = svg.Element.TextElementBase;
+			this.base(node);
+			
+			//								 TEXT			  ELEMENT
+			this.text = node.nodeType == 3 ? node.nodeValue : node.childNodes[0].nodeValue;
+			this.getText = function() {
+				return this.text;
+			}
+		}
+		svg.Element.tspan.prototype = new svg.Element.TextElementBase;
+		
+		// tref
+		svg.Element.tref = function(node) {
+			this.base = svg.Element.TextElementBase;
+			this.base(node);
+			
+			this.getText = function() {
+				var element = this.attribute('xlink:href').Definition.getDefinition();
+				if (element != null) return element.children[0].getText();
+			}
+		}
+		svg.Element.tref.prototype = new svg.Element.TextElementBase;		
+		
+		// group element
+		svg.Element.g = function(node) {
+			this.base = svg.Element.RenderedElementBase;
+			this.base(node);
+		}
+		svg.Element.g.prototype = new svg.Element.RenderedElementBase;
+
+		// symbol element
+		svg.Element.symbol = function(node) {
+			this.base = svg.Element.RenderedElementBase;
+			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;
+			this.base(node);
+			
+			var css = node.childNodes[0].nodeValue;
+			css = css.replace(/(\/\*([^*]|[\r\n]|(\*+([^*\/]|[\r\n])))*\*+\/)|(\/\/.*)/gm, ''); // remove comments
+			css = svg.compressSpaces(css); // replace whitespace
+			var cssDefs = css.split('}');
+			for (var i=0; i<cssDefs.length; i++) {
+				if (svg.trim(cssDefs[i]) != '') {
+					var cssDef = cssDefs[i].split('{');
+					var cssClasses = cssDef[0].split(',');
+					var cssProps = cssDef[1].split(';');
+					for (var j=0; j<cssClasses.length; j++) {
+						var cssClass = svg.trim(cssClasses[j]);
+						if (cssClass != '') {
+							var props = {};
+							for (var k=0; k<cssProps.length; k++) {
+								var prop = cssProps[k].split(':');
+								var name = prop[0];
+								var value = prop[1];
+								if (name != null && value != null) {
+									props[svg.trim(prop[0])] = new svg.Property(svg.trim(prop[0]), svg.trim(prop[1]));
+								}
+							}
+							svg.Styles[cssClass] = props;
+						}
+					}
+
+				}
+			}
+		}
+		svg.Element.style.prototype = new svg.Element.ElementBase;
+		
+		// use element 
+		svg.Element.use = function(node) {
+			this.base = svg.Element.RenderedElementBase;
+			this.base(node);
+			
+			this.baseSetContext = this.setContext;
+			this.setContext = function(ctx) {
+				this.baseSetContext(ctx);
+				if (this.attribute('x').hasValue()) ctx.translate(this.attribute('x').Length.toPixels('x'), 0);
+				if (this.attribute('y').hasValue()) ctx.translate(0, this.attribute('y').Length.toPixels('y'));
+			}
+			
+			this.renderChildren = function(ctx) {
+				var element = this.attribute('xlink:href').Definition.getDefinition();
+				if (element != null) element.render(ctx);
+			}
+		}
+		svg.Element.use.prototype = new svg.Element.RenderedElementBase;
+		
+		// clip element
+		svg.Element.clipPath = function(node) {
+			this.base = svg.Element.ElementBase;
+			this.base(node);
+			
+			this.apply = function(ctx) {
+				for (var i=0; i<this.children.length; i++) {
+					if (this.children[i].path) {
+						this.children[i].path(ctx);
+						ctx.clip();
+					}
+				}
+			}
+		}
+		svg.Element.clipPath.prototype = new svg.Element.ElementBase;
+
+		// title element, do nothing
+		svg.Element.title = function(node) {
+		}
+		svg.Element.title.prototype = new svg.Element.ElementBase;
+
+		// desc element, do nothing
+		svg.Element.desc = function(node) {
+		}
+		svg.Element.desc.prototype = new svg.Element.ElementBase;		
+		
+		svg.Element.MISSING = function(node) {
+			console.log('ERROR: Element \'' + node.nodeName + '\' not yet implemented.');
+		}
+		svg.Element.MISSING.prototype = new svg.Element.ElementBase;
+		
+		// element factory
+		svg.CreateElement = function(node) {
+			var className = 'svg.Element.' + node.nodeName.replace(/^[^:]+:/,'');
+			if (!eval(className)) className = 'svg.Element.MISSING';
+		
+			var e = eval('new ' + className + '(node)');
+			e.type = node.nodeName;
+			return e;
+		}
+				
+		// load from url
+		svg.load = function(ctx, url) {
+			svg.loadXml(ctx, svg.ajax(url));
+		}
+		
+		// load from xml
+		svg.loadXml = function(ctx, xml) {
+			svg.init(ctx);
+		
+			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);
+			}
+			svg.ViewPort.SetCurrent(ctx.canvas.clientWidth, ctx.canvas.clientHeight);
+			
+			// render loop
+			ctx.clearRect(0, 0, ctx.canvas.clientWidth, ctx.canvas.clientHeight);
+			e.render(ctx);
+			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);
+				}
+			
+				// render if needed
+				if (needUpdate) {
+					ctx.clearRect(0, 0, ctx.canvas.clientWidth, ctx.canvas.clientHeight);
+					e.render(ctx);
+				}
+			}, 1000 / svg.FRAMERATE);
+		}
+		
+		svg.stop = function() {
+			if (svg.intervalID) {
+				clearInterval(svg.intervalID);
+			}
+		}
+		
+		return svg;
+	}
+})();

+ 287 - 0
main/inc/lib/svg-edit/canvg/rgbcolor.js

@@ -0,0 +1,287 @@
+/**
+ * A class to parse color values
+ * @author Stoyan Stefanov <sstoo@gmail.com>
+ * @link   http://www.phpied.com/rgb-color-parser-in-javascript/
+ * @license Use it if you like it
+ */
+function RGBColor(color_string)
+{
+    this.ok = false;
+
+    // strip any leading #
+    if (color_string.charAt(0) == '#') { // remove # if any
+        color_string = color_string.substr(1,6);
+    }
+
+    color_string = color_string.replace(/ /g,'');
+    color_string = color_string.toLowerCase();
+
+    // before getting into regexps, try simple matches
+    // and overwrite the input
+    var simple_colors = {
+        aliceblue: 'f0f8ff',
+        antiquewhite: 'faebd7',
+        aqua: '00ffff',
+        aquamarine: '7fffd4',
+        azure: 'f0ffff',
+        beige: 'f5f5dc',
+        bisque: 'ffe4c4',
+        black: '000000',
+        blanchedalmond: 'ffebcd',
+        blue: '0000ff',
+        blueviolet: '8a2be2',
+        brown: 'a52a2a',
+        burlywood: 'deb887',
+        cadetblue: '5f9ea0',
+        chartreuse: '7fff00',
+        chocolate: 'd2691e',
+        coral: 'ff7f50',
+        cornflowerblue: '6495ed',
+        cornsilk: 'fff8dc',
+        crimson: 'dc143c',
+        cyan: '00ffff',
+        darkblue: '00008b',
+        darkcyan: '008b8b',
+        darkgoldenrod: 'b8860b',
+        darkgray: 'a9a9a9',
+        darkgreen: '006400',
+        darkkhaki: 'bdb76b',
+        darkmagenta: '8b008b',
+        darkolivegreen: '556b2f',
+        darkorange: 'ff8c00',
+        darkorchid: '9932cc',
+        darkred: '8b0000',
+        darksalmon: 'e9967a',
+        darkseagreen: '8fbc8f',
+        darkslateblue: '483d8b',
+        darkslategray: '2f4f4f',
+        darkturquoise: '00ced1',
+        darkviolet: '9400d3',
+        deeppink: 'ff1493',
+        deepskyblue: '00bfff',
+        dimgray: '696969',
+        dodgerblue: '1e90ff',
+        feldspar: 'd19275',
+        firebrick: 'b22222',
+        floralwhite: 'fffaf0',
+        forestgreen: '228b22',
+        fuchsia: 'ff00ff',
+        gainsboro: 'dcdcdc',
+        ghostwhite: 'f8f8ff',
+        gold: 'ffd700',
+        goldenrod: 'daa520',
+        gray: '808080',
+        green: '008000',
+        greenyellow: 'adff2f',
+        honeydew: 'f0fff0',
+        hotpink: 'ff69b4',
+        indianred : 'cd5c5c',
+        indigo : '4b0082',
+        ivory: 'fffff0',
+        khaki: 'f0e68c',
+        lavender: 'e6e6fa',
+        lavenderblush: 'fff0f5',
+        lawngreen: '7cfc00',
+        lemonchiffon: 'fffacd',
+        lightblue: 'add8e6',
+        lightcoral: 'f08080',
+        lightcyan: 'e0ffff',
+        lightgoldenrodyellow: 'fafad2',
+        lightgrey: 'd3d3d3',
+        lightgreen: '90ee90',
+        lightpink: 'ffb6c1',
+        lightsalmon: 'ffa07a',
+        lightseagreen: '20b2aa',
+        lightskyblue: '87cefa',
+        lightslateblue: '8470ff',
+        lightslategray: '778899',
+        lightsteelblue: 'b0c4de',
+        lightyellow: 'ffffe0',
+        lime: '00ff00',
+        limegreen: '32cd32',
+        linen: 'faf0e6',
+        magenta: 'ff00ff',
+        maroon: '800000',
+        mediumaquamarine: '66cdaa',
+        mediumblue: '0000cd',
+        mediumorchid: 'ba55d3',
+        mediumpurple: '9370d8',
+        mediumseagreen: '3cb371',
+        mediumslateblue: '7b68ee',
+        mediumspringgreen: '00fa9a',
+        mediumturquoise: '48d1cc',
+        mediumvioletred: 'c71585',
+        midnightblue: '191970',
+        mintcream: 'f5fffa',
+        mistyrose: 'ffe4e1',
+        moccasin: 'ffe4b5',
+        navajowhite: 'ffdead',
+        navy: '000080',
+        oldlace: 'fdf5e6',
+        olive: '808000',
+        olivedrab: '6b8e23',
+        orange: 'ffa500',
+        orangered: 'ff4500',
+        orchid: 'da70d6',
+        palegoldenrod: 'eee8aa',
+        palegreen: '98fb98',
+        paleturquoise: 'afeeee',
+        palevioletred: 'd87093',
+        papayawhip: 'ffefd5',
+        peachpuff: 'ffdab9',
+        peru: 'cd853f',
+        pink: 'ffc0cb',
+        plum: 'dda0dd',
+        powderblue: 'b0e0e6',
+        purple: '800080',
+        red: 'ff0000',
+        rosybrown: 'bc8f8f',
+        royalblue: '4169e1',
+        saddlebrown: '8b4513',
+        salmon: 'fa8072',
+        sandybrown: 'f4a460',
+        seagreen: '2e8b57',
+        seashell: 'fff5ee',
+        sienna: 'a0522d',
+        silver: 'c0c0c0',
+        skyblue: '87ceeb',
+        slateblue: '6a5acd',
+        slategray: '708090',
+        snow: 'fffafa',
+        springgreen: '00ff7f',
+        steelblue: '4682b4',
+        tan: 'd2b48c',
+        teal: '008080',
+        thistle: 'd8bfd8',
+        tomato: 'ff6347',
+        turquoise: '40e0d0',
+        violet: 'ee82ee',
+        violetred: 'd02090',
+        wheat: 'f5deb3',
+        white: 'ffffff',
+        whitesmoke: 'f5f5f5',
+        yellow: 'ffff00',
+        yellowgreen: '9acd32'
+    };
+    for (var key in simple_colors) {
+        if (color_string == key) {
+            color_string = simple_colors[key];
+        }
+    }
+    // emd of simple type-in colors
+
+    // array of color definition objects
+    var color_defs = [
+        {
+            re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
+            example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'],
+            process: function (bits){
+                return [
+                    parseInt(bits[1]),
+                    parseInt(bits[2]),
+                    parseInt(bits[3])
+                ];
+            }
+        },
+        {
+            re: /^(\w{2})(\w{2})(\w{2})$/,
+            example: ['#00ff00', '336699'],
+            process: function (bits){
+                return [
+                    parseInt(bits[1], 16),
+                    parseInt(bits[2], 16),
+                    parseInt(bits[3], 16)
+                ];
+            }
+        },
+        {
+            re: /^(\w{1})(\w{1})(\w{1})$/,
+            example: ['#fb0', 'f0f'],
+            process: function (bits){
+                return [
+                    parseInt(bits[1] + bits[1], 16),
+                    parseInt(bits[2] + bits[2], 16),
+                    parseInt(bits[3] + bits[3], 16)
+                ];
+            }
+        }
+    ];
+
+    // search through the definitions to find a match
+    for (var i = 0; i < color_defs.length; i++) {
+        var re = color_defs[i].re;
+        var processor = color_defs[i].process;
+        var bits = re.exec(color_string);
+        if (bits) {
+            channels = processor(bits);
+            this.r = channels[0];
+            this.g = channels[1];
+            this.b = channels[2];
+            this.ok = true;
+        }
+
+    }
+
+    // validate/cleanup values
+    this.r = (this.r < 0 || isNaN(this.r)) ? 0 : ((this.r > 255) ? 255 : this.r);
+    this.g = (this.g < 0 || isNaN(this.g)) ? 0 : ((this.g > 255) ? 255 : this.g);
+    this.b = (this.b < 0 || isNaN(this.b)) ? 0 : ((this.b > 255) ? 255 : this.b);
+
+    // some getters
+    this.toRGB = function () {
+        return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')';
+    }
+    this.toHex = function () {
+        var r = this.r.toString(16);
+        var g = this.g.toString(16);
+        var b = this.b.toString(16);
+        if (r.length == 1) r = '0' + r;
+        if (g.length == 1) g = '0' + g;
+        if (b.length == 1) b = '0' + b;
+        return '#' + r + g + b;
+    }
+
+    // help
+    this.getHelpXML = function () {
+
+        var examples = new Array();
+        // add regexps
+        for (var i = 0; i < color_defs.length; i++) {
+            var example = color_defs[i].example;
+            for (var j = 0; j < example.length; j++) {
+                examples[examples.length] = example[j];
+            }
+        }
+        // add type-in colors
+        for (var sc in simple_colors) {
+            examples[examples.length] = sc;
+        }
+
+        var xml = document.createElement('ul');
+        xml.setAttribute('id', 'rgbcolor-examples');
+        for (var i = 0; i < examples.length; i++) {
+            try {
+                var list_item = document.createElement('li');
+                var list_color = new RGBColor(examples[i]);
+                var example_div = document.createElement('div');
+                example_div.style.cssText =
+                        'margin: 3px; '
+                        + 'border: 1px solid black; '
+                        + 'background:' + list_color.toHex() + '; '
+                        + 'color:' + list_color.toHex()
+                ;
+                example_div.appendChild(document.createTextNode('test'));
+                var list_item_value = document.createTextNode(
+                    ' ' + examples[i] + ' -> ' + list_color.toRGB() + ' -> ' + list_color.toHex()
+                );
+                list_item.appendChild(example_div);
+                list_item.appendChild(list_item_value);
+                xml.appendChild(list_item);
+
+            } catch(e){}
+        }
+        return xml;
+
+    }
+
+}

+ 157 - 0
main/inc/lib/svg-edit/embedapi.js

@@ -0,0 +1,157 @@
+/*
+function embedded_svg_edit(frame){
+  //initialize communication
+  this.frame = frame;
+  this.stack = []; //callback stack
+  
+  var editapi = this;
+  
+  window.addEventListener("message", function(e){
+    if(e.data.substr(0,5) == "ERROR"){
+      editapi.stack.splice(0,1)[0](e.data,"error")
+    }else{
+      editapi.stack.splice(0,1)[0](e.data)
+    }
+  }, false)
+}
+
+embedded_svg_edit.prototype.call = function(code, callback){
+  this.stack.push(callback);
+  this.frame.contentWindow.postMessage(code,"*");
+}
+
+embedded_svg_edit.prototype.getSvgString = function(callback){
+  this.call("svgCanvas.getSvgString()",callback)
+}
+
+embedded_svg_edit.prototype.setSvgString = function(svg){
+  this.call("svgCanvas.setSvgString('"+svg.replace(/'/g, "\\'")+"')");
+}
+*/
+
+
+/*
+Embedded SVG-edit API
+
+General usage:
+- Have an iframe somewhere pointing to a version of svg-edit > r1000
+- Initialize the magic with:
+var svgCanvas = new embedded_svg_edit(window.frames['svgedit']);
+- Pass functions in this format:
+svgCanvas.setSvgString("string")
+- Or if a callback is needed:
+svgCanvas.setSvgString("string")(function(data, error){
+  if(error){
+    //there was an error
+  }else{
+    //handle data
+  }
+})
+
+Everything is done with the same API as the real svg-edit, 
+and all documentation is unchanged. The only difference is
+when handling returns, the callback notation is used instead. 
+
+var blah = new embedded_svg_edit(window.frames['svgedit']);
+blah.clearSelection("woot","blah",1337,[1,2,3,4,5,"moo"],-42,{a: "tree",b:6, c: 9})(function(){console.log("GET DATA",arguments)})
+*/
+
+function embedded_svg_edit(frame){
+  //initialize communication
+  this.frame = frame;
+  //this.stack = [] //callback stack
+  this.callbacks = {}; //successor to stack
+  this.encode = embedded_svg_edit.encode;
+  //List of functions extracted with this:
+  //Run in firebug on http://svg-edit.googlecode.com/svn/trunk/docs/files/svgcanvas-js.html
+  
+  //for(var i=0,q=[],f = document.querySelectorAll("div.CFunction h3.CTitle a");i<f.length;i++){q.push(f[i].name)};q
+  //var functions = ["clearSelection", "addToSelection", "removeFromSelection", "open", "save", "getSvgString", "setSvgString", "createLayer", "deleteCurrentLayer", "getNumLayers", "getLayer", "getCurrentLayer", "setCurrentLayer", "renameCurrentLayer", "setCurrentLayerPosition", "getLayerVisibility", "setLayerVisibility", "moveSelectedToLayer", "getLayerOpacity", "setLayerOpacity", "clear"];
+  
+  
+  //Newer, well, it extracts things that aren't documented as well. All functions accessible through the normal thingy can now be accessed though the API
+  //var l=[];for(var i in svgCanvas){if(typeof svgCanvas[i] == "function"){l.push(i)}};
+  //run in svgedit itself
+  var functions = ["updateElementFromJson", "embedImage", "fixOperaXML", "clearSelection", "addToSelection", "removeFromSelection", "addNodeToSelection", "open", "save", "getSvgString", "setSvgString", "createLayer", "deleteCurrentLayer", "getNumLayers", "getLayer", "getCurrentLayer", "setCurrentLayer", "renameCurrentLayer", "setCurrentLayerPosition", "getLayerVisibility", "setLayerVisibility", "moveSelectedToLayer", "getLayerOpacity", "setLayerOpacity", "clear", "clearPath", "getNodePoint", "clonePathNode", "deletePathNode", "getResolution", "getImageTitle", "setImageTitle", "setResolution", "setBBoxZoom", "setZoom", "getMode", "setMode", "getStrokeColor", "setStrokeColor", "getFillColor", "setFillColor", "setStrokePaint", "setFillPaint", "getStrokeWidth", "setStrokeWidth", "getStrokeStyle", "setStrokeStyle", "getOpacity", "setOpacity", "getFillOpacity", "setFillOpacity", "getStrokeOpacity", "setStrokeOpacity", "getTransformList", "getBBox", "getRotationAngle", "setRotationAngle", "each", "bind", "setIdPrefix", "getBold", "setBold", "getItalic", "setItalic", "getFontFamily", "setFontFamily", "getFontSize", "setFontSize", "getText", "setTextContent", "setImageURL", "setRectRadius", "setSegType", "quickClone", "beginUndoableChange", "changeSelectedAttributeNoUndo", "finishUndoableChange", "changeSelectedAttribute", "deleteSelectedElements", "groupSelectedElements", "ungroupSelectedElement", "moveToTopSelectedElement", "moveToBottomSelectedElement", "moveSelectedElements", "getStrokedBBox", "getVisibleElements", "cycleElement", "getUndoStackSize", "getRedoStackSize", "getNextUndoCommandText", "getNextRedoCommandText", "undo", "redo", "cloneSelectedElements", "alignSelectedElements", "getZoom", "getVersion", "setIconSize", "setLang", "setCustomHandlers"]
+  
+  //TODO: rewrite the following, it's pretty scary.
+  for(var i = 0; i < functions.length; i++){
+    this[functions[i]] = (function(d){
+      return function(){
+        var t = this //new callback
+        for(var g = 0, args = []; g < arguments.length; g++){
+          args.push(arguments[g]);
+        }
+        var cbid = t.send(d,args, function(){})  //the callback (currently it's nothing, but will be set later
+        
+        return function(newcallback){
+          t.callbacks[cbid] = newcallback; //set callback
+        }
+      }
+    })(functions[i])
+  }
+  //TODO: use AddEvent for Trident browsers, currently they dont support SVG, but they do support onmessage
+  var t = this;
+  window.addEventListener("message", function(e){
+    if(e.data.substr(0,4)=="SVGe"){ //because svg-edit is too longish
+      var data = e.data.substr(4);
+      var cbid = data.substr(0, data.indexOf(";"));
+      if(t.callbacks[cbid]){
+        if(data.substr(0,6) != "error:"){
+          t.callbacks[cbid](eval("("+data.substr(cbid.length+1)+")"))
+        }else{
+          t.callbacks[cbid](data, "error");
+        }
+      }
+    }
+    //this.stack.shift()[0](e.data,e.data.substr(0,5) == "ERROR"?'error':null) //replace with shift
+  }, false)
+}
+
+embedded_svg_edit.encode = function(obj){
+  //simple partial JSON encoder implementation
+  if(window.JSON && JSON.stringify) return JSON.stringify(obj);
+  var enc = arguments.callee; //for purposes of recursion
+  
+  if(typeof obj == "boolean" || typeof obj == "number"){
+      return obj+'' //should work...
+  }else if(typeof obj == "string"){
+    //a large portion of this is stolen from Douglas Crockford's json2.js
+    return '"'+
+          obj.replace(
+            /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g
+          , function (a) {
+            return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+          })
+          +'"'; //note that this isn't quite as purtyful as the usualness
+  }else if(obj.length){ //simple hackish test for arrayish-ness
+    for(var i = 0; i < obj.length; i++){
+      obj[i] = enc(obj[i]); //encode every sub-thingy on top
+    }
+    return "["+obj.join(",")+"]";
+  }else{
+    var pairs = []; //pairs will be stored here
+    for(var k in obj){ //loop through thingys
+      pairs.push(enc(k)+":"+enc(obj[k])); //key: value
+    }
+    return "{"+pairs.join(",")+"}" //wrap in the braces
+  }
+}
+
+embedded_svg_edit.prototype.send = function(name, args, callback){
+  var cbid = Math.floor(Math.random()*31776352877+993577).toString();
+  //this.stack.push(callback);
+  this.callbacks[cbid] = callback;
+  for(var argstr = [], i = 0; i < args.length; i++){
+    argstr.push(this.encode(args[i]))
+  }
+  var t = this;
+  setTimeout(function(){//delay for the callback to be set in case its synchronous
+    t.frame.contentWindow.postMessage(cbid+";svgCanvas['"+name+"']("+argstr.join(",")+")","*");
+  }, 0);
+  return cbid;
+  //this.stack.shift()("svgCanvas['"+name+"']("+argstr.join(",")+")")
+}
+
+
+

+ 41 - 0
main/inc/lib/svg-edit/extensions/closepath_icons.svg

@@ -0,0 +1,41 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+<g id="tool_closepath">
+<svg viewBox="0 0 300 300" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <g>
+  <title>Layer 1</title>
+  <path stroke="#000" stroke-width="15" fill="#ffc8c8" d="m121.5,40l-84,106l27,115l166,2l29,-111"/>
+  <line x1="240" y1="136" x2="169.5" y2="74" stroke="#A00" stroke-width="25" fill="none"/>
+  <path stroke="none" fill ="#A00" d="m158,65l31,74l-3,-50l51,-3z"/>
+  <g stroke-width="15" stroke="#00f" fill="#0ff">
+  <circle r="30" cy="41" cx="123"/>
+  <circle r="30" cy="146" cx="40"/>
+  <circle r="30" cy="260" cx="69"/>
+  <circle r="30" cy="260" cx="228"/>
+  <circle r="30" cy="148" cx="260"/>
+  </g>
+ </g>
+</svg>
+</g>
+<g id="tool_openpath">
+<svg viewBox="0 0 300 300" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <g>
+  <title>Layer 1</title>
+  <path stroke="#000" stroke-width="15" fill="#ffc8c8" d="m123.5,38l-84,106l27,115l166,2l29,-111"/>
+  <line x1="276.5" y1="153" x2="108.5" y2="24" stroke="#000" stroke-width="10" fill="none"/>
+  <g stroke-width="15" stroke="#00f" fill="#0ff">
+   <circle r="30" cy="41" cx="123"/>
+   <circle r="30" cy="146" cx="40"/>
+   <circle r="30" cy="260" cx="69"/>
+   <circle r="30" cy="260" cx="228"/>
+   <circle r="30" cy="148" cx="260"/>
+  </g>
+  <g  stroke="#A00" stroke-width="15" fill="none">
+   <line x1="168" y1="24" x2="210" y2="150"/>
+   <line x1="210" y1="24" x2="168" y2="150"/>
+  </g>
+ </g>
+</svg>
+</g>
+
+<g id="svg_eof"/>
+</svg>

+ 298 - 0
main/inc/lib/svg-edit/extensions/ext-arrows.js

@@ -0,0 +1,298 @@
+/*
+ * ext-arrows.js
+ *
+ * Licensed under the Apache License, Version 2
+ *
+ * Copyright(c) 2010 Alexis Deveria
+ *
+ */
+
+ 
+svgEditor.addExtension("Arrows", function(S) {
+		var svgcontent = S.svgcontent,
+			addElem = S.addSvgElementFromJson,
+			nonce = S.nonce,
+			randomize_ids = S.randomize_ids,
+			selElems;
+
+		svgCanvas.bind('setarrownonce', setArrowNonce);
+		svgCanvas.bind('unsetsetarrownonce', unsetArrowNonce);
+			
+		var lang_list = {
+			"en":[
+				{"id": "arrow_none", "textContent": "No arrow" }
+			],
+			"fr":[
+				{"id": "arrow_none", "textContent": "Sans flèche" }
+			]
+		};
+		
+		var prefix = 'se_arrow_';
+		if (randomize_ids) {
+		  var arrowprefix = prefix + nonce + '_';
+		} else {
+		  var arrowprefix = prefix;
+		}
+
+		var pathdata = {
+			fw: {d:"m0,0l10,5l-10,5l5,-5l-5,-5z", refx:8,  id: arrowprefix + 'fw'},
+			bk: {d:"m10,0l-10,5l10,5l-5,-5l5,-5z", refx:2, id: arrowprefix + 'bk'}
+		}
+		
+		function setArrowNonce(window, n) {
+		    randomize_ids = true;
+		    arrowprefix = prefix + n + '_';
+ 			pathdata.fw.id = arrowprefix + 'fw';
+			pathdata.bk.id = arrowprefix + 'bk';
+		}
+
+		function unsetArrowNonce(window) {
+		    randomize_ids = false;
+		    arrowprefix = prefix;
+ 			pathdata.fw.id = arrowprefix + 'fw';
+			pathdata.bk.id = arrowprefix + 'bk';
+		}
+
+		function getLinked(elem, attr) {
+			var str = elem.getAttribute(attr);
+			if(!str) return null;
+			var m = str.match(/\(\#(.*)\)/);
+			if(!m || m.length !== 2) {
+				return null;
+			}
+			return S.getElem(m[1]);
+		}
+		
+		function showPanel(on) {
+			$('#arrow_panel').toggle(on);
+			
+			if(on) {
+				var el = selElems[0];
+				var end = el.getAttribute("marker-end");
+				var start = el.getAttribute("marker-start");
+				var mid = el.getAttribute("marker-mid");
+				var val;
+				
+				if(end && start) {
+					val = "both";
+				} else if(end) {
+					val = "end";
+				} else if(start) {
+					val = "start";
+				} else if(mid) {
+					val = "mid";
+					if(mid.indexOf("bk") != -1) {
+						val = "mid_bk";
+					}
+				}
+				
+				if(!start && !mid && !end) {
+					val = "none";
+				}
+				
+				$("#arrow_list").val(val);
+			}
+		}
+		
+		function resetMarker() {
+			var el = selElems[0];
+			el.removeAttribute("marker-start");
+			el.removeAttribute("marker-mid");
+			el.removeAttribute("marker-end");
+		}
+		
+		function addMarker(dir, type, id) {
+			// TODO: Make marker (or use?) per arrow type, since refX can be different
+			id = id || arrowprefix + dir;
+			
+			var marker = S.getElem(id);
+
+			var data = pathdata[dir];
+			
+			if(type == "mid") {
+				data.refx = 5;
+			}
+
+			if(!marker) {
+				marker = addElem({
+					"element": "marker",
+					"attr": {
+						"viewBox": "0 0 10 10",
+						"id": id,
+						"refY": 5,
+						"markerUnits": "strokeWidth",
+						"markerWidth": 5,
+						"markerHeight": 5,
+						"orient": "auto",
+						"style": "pointer-events:none" // Currently needed for Opera
+					}
+				});
+				var arrow = addElem({
+					"element": "path",
+					"attr": {
+						"d": data.d,
+						"fill": "#000000"
+					}
+				});
+				marker.appendChild(arrow);
+				S.findDefs().appendChild(marker);
+			} 
+			
+			marker.setAttribute('refX', data.refx);
+			
+			return marker;
+		}
+		
+		function setArrow() {
+			var type = this.value;
+			resetMarker();
+		
+			if(type == "none") {
+				return;
+			}
+		
+			// Set marker on element
+			var dir = "fw";
+			if(type == "mid_bk") {
+				type = "mid";
+				dir = "bk";
+			} else if(type == "both") {
+				addMarker("bk", type);
+				svgCanvas.changeSelectedAttribute("marker-start", "url(#" + pathdata.bk.id + ")");
+				type = "end";
+				dir = "fw";
+			} else if (type == "start") {
+				dir = "bk";
+			}
+			
+			addMarker(dir, type);
+			svgCanvas.changeSelectedAttribute("marker-"+type, "url(#" + pathdata[dir].id + ")");
+			S.call("changed", selElems);
+		}
+		
+		function colorChanged(elem) {
+			var color = elem.getAttribute('stroke');
+			
+			var mtypes = ['start','mid','end'];
+			var defs = S.findDefs();
+			
+			$.each(mtypes, function(i, type) {
+				var marker = getLinked(elem, 'marker-'+type);
+				if(!marker) return;
+				
+				var cur_color = $(marker).children().attr('fill');
+				var cur_d = $(marker).children().attr('d');
+				var new_marker = null;
+				if(cur_color === color) return;
+				
+				var all_markers = $(defs).find('marker');
+				// Different color, check if already made
+				all_markers.each(function() {
+					var attrs = $(this).children().attr(['fill', 'd']);
+					if(attrs.fill === color && attrs.d === cur_d) {
+						// Found another marker with this color and this path
+						new_marker = this;
+					}
+				});
+				
+				if(!new_marker) {
+					// Create a new marker with this color
+					var last_id = marker.id;
+					var dir = last_id.indexOf('_fw') !== -1?'fw':'bk';
+					
+					new_marker = addMarker(dir, type, arrowprefix + dir + all_markers.length);
+
+					$(new_marker).children().attr('fill', color);
+				}
+				
+				$(elem).attr('marker-'+type, "url(#" + new_marker.id + ")");
+				
+				// Check if last marker can be removed
+				var remove = true;
+				$(S.svgcontent).find('line, polyline, path, polygon').each(function() {
+					var elem = this;
+					$.each(mtypes, function(j, mtype) {
+						if($(elem).attr('marker-' + mtype) === "url(#" + marker.id + ")") {
+							return remove = false;
+						}
+					});
+					if(!remove) return false;
+				});
+				
+				// Not found, so can safely remove
+				if(remove) {
+					$(marker).remove();
+				}
+
+			});
+			
+		}
+		
+		return {
+			name: "Arrows",
+			context_tools: [{
+				type: "select",
+				panel: "arrow_panel",
+				title: "Select arrow type",
+				id: "arrow_list",
+				options: {
+					none: "No arrow",
+					end: "----&gt;",
+					start: "&lt;----",
+					both: "&lt;---&gt;",
+					mid: "--&gt;--",
+					mid_bk: "--&lt;--"
+				},
+				defval: "none",
+				events: {
+					change: setArrow
+				}
+			}],
+			callback: function() {
+				$('#arrow_panel').hide();
+				// Set ID so it can be translated in locale file
+				$('#arrow_list option')[0].id = 'connector_no_arrow';
+			},
+			addLangData: function(lang) {
+				return {
+					data: lang_list[lang]
+				};
+			},
+			selectedChanged: function(opts) {
+				
+				// Use this to update the current selected elements
+				selElems = opts.elems;
+				
+				var i = selElems.length;
+				var marker_elems = ['line','path','polyline','polygon'];
+				
+				while(i--) {
+					var elem = selElems[i];
+					if(elem && $.inArray(elem.tagName, marker_elems) != -1) {
+						if(opts.selectedElement && !opts.multiselected) {
+							showPanel(true);
+						} else {
+							showPanel(false);
+						}
+					} else {
+						showPanel(false);
+					}
+				}
+			},
+			elementChanged: function(opts) {
+				var elem = opts.elems[0];
+				if(elem && (
+					elem.getAttribute("marker-start") ||
+					elem.getAttribute("marker-mid") ||
+					elem.getAttribute("marker-end")
+				)) {
+	// 								var start = elem.getAttribute("marker-start");
+	// 								var mid = elem.getAttribute("marker-mid");
+	// 								var end = elem.getAttribute("marker-end");
+					// Has marker, so see if it should match color
+					colorChanged(elem);
+				}
+				
+			}
+		};
+});

+ 92 - 0
main/inc/lib/svg-edit/extensions/ext-closepath.js

@@ -0,0 +1,92 @@
+/*
+ * ext-closepath.js
+ *
+ * Licensed under the Apache License, Version 2
+ *
+ * Copyright(c) 2010 Jeff Schiller
+ *
+ */
+
+// This extension adds a simple button to the contextual panel for paths
+// The button toggles whether the path is open or closed
+svgEditor.addExtension("ClosePath", function(S) {
+		var selElems,
+			updateButton = function(path) {
+				var seglist = path.pathSegList,
+					closed = seglist.getItem(seglist.numberOfItems - 1).pathSegType==1,
+					showbutton = closed ? '#tool_openpath' : '#tool_closepath',
+					hidebutton = closed ? '#tool_closepath' : '#tool_openpath';
+					$(hidebutton).hide();
+					$(showbutton).show();
+			},
+			showPanel = function(on) {
+				$('#closepath_panel').toggle(on);
+				if (on) {
+					var path = selElems[0];
+					if (path) updateButton(path);
+				}
+			},
+		
+			toggleClosed = function() {
+				var path = selElems[0];
+				if (path) {
+					var seglist = path.pathSegList,
+						last = seglist.numberOfItems - 1;					
+					// is closed
+					if(seglist.getItem(last).pathSegType == 1) {
+						seglist.removeItem(last);
+					}
+					else {
+						seglist.appendItem(path.createSVGPathSegClosePath());
+					}
+					updateButton(path);
+				}
+			};
+		
+		return {
+			name: "ClosePath",
+			svgicons: "extensions/closepath_icons.svg",
+			buttons: [{
+				id: "tool_openpath",
+				type: "context",
+				panel: "closepath_panel",
+				title: "Open path",
+				events: {
+					'click': function() {
+						toggleClosed();
+					}
+				}
+			},
+			{
+				id: "tool_closepath",
+				type: "context",
+				panel: "closepath_panel",
+				title: "Close path",
+				events: {
+					'click': function() {
+						toggleClosed();
+					}
+				}
+			}],
+			callback: function() {
+				$('#closepath_panel').hide();
+			},
+			selectedChanged: function(opts) {
+				selElems = opts.elems;
+				var i = selElems.length;
+				
+				while(i--) {
+					var elem = selElems[i];
+					if(elem && elem.tagName == 'path') {
+						if(opts.selectedElement && !opts.multiselected) {
+							showPanel(true);
+						} else {
+							showPanel(false);
+						}
+					} else {
+						showPanel(false);
+					}
+				}
+			}
+		};
+});

+ 579 - 0
main/inc/lib/svg-edit/extensions/ext-connector.js

@@ -0,0 +1,579 @@
+/*
+ * ext-connector.js
+ *
+ * Licensed under the Apache License, Version 2
+ *
+ * Copyright(c) 2010 Alexis Deveria
+ *
+ */
+ 
+svgEditor.addExtension("Connector", function(S) {
+	var svgcontent = S.svgcontent,
+		svgroot = S.svgroot,
+		getNextId = S.getNextId,
+		getElem = S.getElem,
+		addElem = S.addSvgElementFromJson,
+		selManager = S.selectorManager,
+		curConfig = svgEditor.curConfig,
+		started = false,
+		start_x,
+		start_y,
+		cur_line,
+		start_elem,
+		end_elem,
+		connections = [],
+		conn_sel = ".se_connector",
+		se_ns,
+// 			connect_str = "-SE_CONNECT-",
+		selElems = [];
+		
+	var lang_list = {
+		"en":[
+			{"id": "mode_connect", "title": "Connect two objects" }
+		],
+		"fr":[
+			{"id": "mode_connect", "title": "Connecter deux objets"}
+		]
+	};
+	
+	function getOffset(side, line) {
+		var give_offset = !!line.getAttribute('marker-' + side);
+// 		var give_offset = $(line).data(side+'_off');
+
+		// TODO: Make this number (5) be based on marker width/height
+		var size = line.getAttribute('stroke-width') * 5;
+		return give_offset ? size : 0;
+	}
+	
+	function showPanel(on) {
+		var conn_rules = $('#connector_rules');
+		if(!conn_rules.length) {
+			conn_rules = $('<style id="connector_rules"><\/style>').appendTo('head');
+		} 
+		conn_rules.text(!on?"":"#tool_clone, #tool_topath, #tool_angle, #xy_panel { display: none !important; }");
+		$('#connector_panel').toggle(on);
+	}
+	
+	function setPoint(elem, pos, x, y, setMid) {
+		var pts = elem.points;
+		var pt = svgroot.createSVGPoint();
+		pt.x = x;
+		pt.y = y;
+		if(pos === 'end') pos = pts.numberOfItems-1;
+		// TODO: Test for this on init, then use alt only if needed
+		try {
+			pts.replaceItem(pt, pos);
+		} catch(err) {
+			// Should only occur in FF which formats points attr as "n,n n,n", so just split
+			var pt_arr = elem.getAttribute("points").split(" ");
+			for(var i=0; i< pt_arr.length; i++) {
+				if(i == pos) {
+					pt_arr[i] = x + ',' + y;
+				}
+			}
+			elem.setAttribute("points",pt_arr.join(" ")); 
+		}
+		
+		if(setMid) {
+			// Add center point
+			var pt_start = pts.getItem(0);
+			var pt_end = pts.getItem(pts.numberOfItems-1);
+			setPoint(elem, 1, (pt_end.x + pt_start.x)/2, (pt_end.y + pt_start.y)/2);
+		}
+	}
+	
+	function updateLine(diff_x, diff_y) {
+		// Update line with element
+		var i = connections.length;
+		while(i--) {
+			var conn = connections[i];
+			var line = conn.connector;
+			var elem = conn.elem;
+			
+			var pre = conn.is_start?'start':'end';
+// 						var sw = line.getAttribute('stroke-width') * 5;
+			
+			// Update bbox for this element
+			var bb = $(line).data(pre+'_bb');
+			bb.x = conn.start_x + diff_x;
+			bb.y = conn.start_y + diff_y;
+			$(line).data(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 src_x = bb2.x + bb2.width/2;
+			var src_y = bb2.y + bb2.height/2;
+			
+			// Set point of element being moved
+			var pt = getBBintersect(src_x, src_y, bb, getOffset(pre, line)); // $(line).data(pre+'_off')?sw:0
+			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));
+			setPoint(line, conn.is_start?'end':0, pt2.x, pt2.y, true);
+
+		}
+	}
+	
+	function findConnectors(elems) {
+		if(!elems) elems = selElems;
+		var connectors = $(svgcontent).find(conn_sel);
+		connections = [];
+
+		// 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 parts = [getElem(start), getElem(end)];
+			for(var i=0; i<2; i++) {
+				var c_elem = parts[i];
+				var add_this = false;
+				// The connected element might be part of a selected group
+				$(c_elem).parents().each(function() {
+					if($.inArray(this, elems) !== -1) {
+						// Pretend this element is selected
+						add_this = true;
+					}
+				});
+				
+				if(!c_elem || !c_elem.parentNode) {
+					$(this).remove();
+					continue;
+				}
+				if($.inArray(c_elem, elems) !== -1 || add_this) {
+					var bb = svgCanvas.getStrokedBBox([c_elem]);
+					connections.push({
+						elem: c_elem,
+						connector: this,
+						is_start: (i === 0),
+						start_x: bb.x,
+						start_y: bb.y
+					});	
+				}
+			}
+		});
+	}
+	
+	function updateConnectors(elems) {
+		// Updates connector lines based on selected elements
+		// Is not used on mousemove, as it runs getStrokedBBox every time,
+		// which isn't necessary there.
+		findConnectors(elems);
+		if(connections.length) {
+			// Update line with element
+			var i = connections.length;
+			while(i--) {
+				var conn = connections[i];
+				var line = conn.connector;
+				var elem = conn.elem;
+
+				var sw = line.getAttribute('stroke-width') * 5;
+				var pre = conn.is_start?'start':'end';
+				
+				// Update bbox for this element
+				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');
+			
+				var alt_pre = conn.is_start?'end':'start';
+				
+				// Get center pt of connected element
+				var bb2 = $(line).data(alt_pre+'_bb');
+				var src_x = bb2.x + bb2.width/2;
+				var src_y = bb2.y + bb2.height/2;
+				
+				// Set point of element being moved
+				var pt = getBBintersect(src_x, src_y, bb, getOffset(pre, line));
+				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));
+				setPoint(line, conn.is_start?'end':0, pt2.x, pt2.y, true);
+				
+				// Update points attribute manually for webkit
+				if(navigator.userAgent.indexOf('AppleWebKit') != -1) {
+					var pts = line.points;
+					var len = pts.numberOfItems;
+					var pt_arr = Array(len);
+					for(var j=0; j< len; j++) {
+						var pt = pts.getItem(j);
+						pt_arr[j] = pt.x + ',' + pt.y;
+					}	
+					line.setAttribute("points",pt_arr.join(" ")); 
+				}
+
+			}
+		}
+	}
+	
+	function getBBintersect(x, y, bb, offset) {
+		if(offset) {
+			offset -= 0;
+			bb = $.extend({}, bb);
+			bb.width += offset;
+			bb.height += offset;
+			bb.x -= offset/2;
+			bb.y -= offset/2;
+		}
+	
+		var mid_x = bb.x + bb.width/2;
+		var mid_y = bb.y + bb.height/2;
+		var len_x = x - mid_x;
+		var len_y = y - mid_y;
+		
+		var slope = Math.abs(len_y/len_x);
+		
+		var ratio;
+		
+		if(slope < bb.height/bb.width) {
+			ratio = (bb.width/2) / Math.abs(len_x);
+		} else {
+			ratio = (bb.height/2) / Math.abs(len_y);
+		}
+		
+		
+		return {
+			x: mid_x + len_x * ratio,
+			y: mid_y + len_y * ratio
+		}
+	}
+	
+	// Do once
+	(function() {
+		var gse = svgCanvas.groupSelectedElements;
+		
+		svgCanvas.groupSelectedElements = function() {
+			svgCanvas.removeFromSelection($(conn_sel).toArray());
+			gse();
+		}
+		
+		var mse = svgCanvas.moveSelectedElements;
+		
+		svgCanvas.moveSelectedElements = function() {
+			svgCanvas.removeFromSelection($(conn_sel).toArray());
+			mse.apply(this, arguments);
+			updateConnectors();
+		}
+		
+		se_ns = svgCanvas.getEditorNS();
+	}());
+	
+	// Do on reset
+	function init() {
+		// Make sure all connectors have data set
+		$(svgcontent).find('*').each(function() { 
+			var conn = this.getAttributeNS(se_ns, "connector");
+			if(conn) {
+				this.setAttribute('class', conn_sel.substr(1));
+				var conn_data = conn.split(' ');
+				var sbb = svgCanvas.getStrokedBBox([getElem(conn_data[0])]);
+				var ebb = svgCanvas.getStrokedBBox([getElem(conn_data[1])]);
+				$(this).data('c_start',conn_data[0])
+					.data('c_end',conn_data[1])
+					.data('start_bb', sbb)
+					.data('end_bb', ebb);
+				svgCanvas.getEditorNS(true);
+			}
+		});
+// 			updateConnectors();
+	}
+	
+// 		$(svgroot).parent().mousemove(function(e) {
+// // 			if(started 
+// // 				|| svgCanvas.getMode() != "connector"
+// // 				|| e.target.parentNode.parentNode != svgcontent) return;
+// 			
+// 			console.log('y')
+// // 			if(e.target.parentNode.parentNode === svgcontent) {
+// // 					
+// // 			}
+// 		});
+	
+	return {
+		name: "Connector",
+		svgicons: "images/conn.svg",
+		buttons: [{
+			id: "mode_connect",
+			type: "mode",
+			icon: "images/cut.png",
+			title: "Connect two objects",
+			key: "Shift+3",
+			includeWith: {
+				button: '#tool_line',
+				isDefault: false,
+				position: 1
+			},
+			events: {
+				'click': function() {
+					svgCanvas.setMode("connector");
+				}
+			}
+		}],
+		addLangData: function(lang) {
+			return {
+				data: lang_list[lang]
+			};
+		},
+		mouseDown: function(opts) {
+			var e = opts.event;
+			start_x = opts.start_x,
+			start_y = opts.start_y;
+			var mode = svgCanvas.getMode();
+			
+			if(mode == "connector") {
+				
+				if(started) return;
+				
+				var mouse_target = e.target;
+				
+				var parents = $(mouse_target).parents();
+				
+				if($.inArray(svgcontent, parents) != -1) {
+					// Connectable element
+					
+					// If child of foreignObject, use parent
+					var fo = $(mouse_target).closest("foreignObject");
+					start_elem = fo.length ? fo[0] : mouse_target;
+					
+					// Get center of source element
+					var bb = svgCanvas.getStrokedBBox([start_elem]);
+					var x = bb.x + bb.width/2;
+					var y = bb.y + bb.height/2;
+					
+					started = true;
+					cur_line = addElem({
+						"element": "polyline",
+						"attr": {
+							"id": getNextId(),
+							"points": (x+','+y+' '+x+','+y+' '+start_x+','+start_y),
+							"stroke": '#' + curConfig.initStroke.color,
+							"stroke-width": (!start_elem.stroke_width || start_elem.stroke_width == 0) ? curConfig.initStroke.width : start_elem.stroke_width,
+							"fill": "none",
+							"opacity": curConfig.initStroke.opacity,
+							"style": "pointer-events:none"
+						}
+					});
+					$(cur_line).data('start_bb', bb);
+				}
+				return {
+					started: true
+				};
+			} else if(mode == "select") {
+				findConnectors();
+			}
+		},
+		mouseMove: function(opts) {
+			var zoom = svgCanvas.getZoom();
+			var e = opts.event;
+			var x = opts.mouse_x/zoom;
+			var y = opts.mouse_y/zoom;
+			
+			var	diff_x = x - start_x,
+				diff_y = y - start_y;
+								
+			var mode = svgCanvas.getMode();
+			
+			if(mode == "connector" && started) {
+				
+				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));
+				start_x = pt.x;
+				start_y = pt.y;
+				
+				setPoint(cur_line, 0, pt.x, pt.y, true);
+				
+				// Set end point
+				setPoint(cur_line, 'end', x, y, true);
+			} else if(mode == "select") {
+				var slen = selElems.length;
+				
+				while(slen--) {
+					var elem = selElems[slen];
+					// Look for selected connector elements
+					if(elem && $(elem).data('c_start')) {
+						// Remove the "translate" transform given to move
+						svgCanvas.removeFromSelection([elem]);
+						svgCanvas.getTransformList(elem).clear();
+
+					}
+				}
+				if(connections.length) {
+					updateLine(diff_x, diff_y);
+
+					
+				}
+			} 
+		},
+		mouseUp: function(opts) {
+			var zoom = svgCanvas.getZoom();
+			var e = opts.event,
+				x = opts.mouse_x/zoom,
+				y = opts.mouse_y/zoom,
+				mouse_target = e.target;
+			
+			if(svgCanvas.getMode() == "connector") {
+				var fo = $(mouse_target).closest("foreignObject");
+				if(fo.length) mouse_target = fo[0];
+				
+				var parents = $(mouse_target).parents();
+
+				if(mouse_target == start_elem) {
+					// Start line through click
+					started = true;
+					return {
+						keep: true,
+						element: null,
+						started: started
+					}						
+				} else if($.inArray(svgcontent, parents) === -1) {
+					// Not a valid target element, so remove line
+					$(cur_line).remove();
+					started = false;
+					return {
+						keep: false,
+						element: null,
+						started: started
+					}
+				} else {
+					// Valid end element
+					end_elem = mouse_target;
+					
+					var start_id = start_elem.id, end_id = end_elem.id;
+					var conn_str = start_id + " " + end_id;
+					var alt_str = end_id + " " + start_id;
+					// Don't create connector if one already exists
+					var dupe = $(svgcontent).find(conn_sel).filter(function() {
+						var conn = this.getAttributeNS(se_ns, "connector");
+						if(conn == conn_str || conn == alt_str) return true;
+					});
+					if(dupe.length) {
+						$(cur_line).remove();
+						return {
+							keep: false,
+							element: null,
+							started: false
+						}
+					}
+					
+					var bb = svgCanvas.getStrokedBBox([end_elem]);
+					
+					var pt = getBBintersect(start_x, start_y, bb, getOffset('start', cur_line));
+					setPoint(cur_line, 'end', pt.x, pt.y, true);
+					$(cur_line)
+						.data("c_start", start_id)
+						.data("c_end", end_id)
+						.data("end_bb", bb);
+					se_ns = svgCanvas.getEditorNS(true);
+					cur_line.setAttributeNS(se_ns, "se:connector", conn_str);
+					cur_line.setAttribute('class', conn_sel.substr(1));
+					cur_line.setAttribute('opacity', 1);
+					svgCanvas.addToSelection([cur_line]);
+					svgCanvas.moveToBottomSelectedElement();
+					selManager.requestSelector(cur_line).showGrips(false);
+					started = false;
+					return {
+						keep: true,
+						element: cur_line,
+						started: started
+					}
+				}
+			}
+		},
+		selectedChanged: function(opts) {
+			
+			// Use this to update the current selected elements
+			selElems = opts.elems;
+			
+			var i = selElems.length;
+			
+			while(i--) {
+				var elem = selElems[i];
+				if(elem && $(elem).data('c_start')) {
+					selManager.requestSelector(elem).showGrips(false);
+					if(opts.selectedElement && !opts.multiselected) {
+						// TODO: Set up context tools and hide most regular line tools
+						showPanel(true);
+					} else {
+						showPanel(false);
+					}
+				} else {
+					showPanel(false);
+				}
+			}
+			updateConnectors();
+		},
+		elementChanged: function(opts) {
+			var elem = opts.elems[0];
+			if (elem && elem.tagName == 'svg' && elem.id == "svgcontent") {
+				// Update svgcontent (can change on import)
+				svgcontent = elem;
+				init();
+			}
+			
+			// Has marker, so change offset
+			if(elem && (
+				elem.getAttribute("marker-start") ||
+				elem.getAttribute("marker-mid") ||
+				elem.getAttribute("marker-end")
+			)) {
+				var start = elem.getAttribute("marker-start");
+				var mid = elem.getAttribute("marker-mid");
+				var end = elem.getAttribute("marker-end");
+				cur_line = elem;
+				$(elem)
+					.data("start_off", !!start)
+					.data("end_off", !!end);
+				
+				if(elem.tagName == "line" && mid) {
+					// Convert to polyline to accept mid-arrow
+					
+					var x1 = elem.getAttribute('x1')-0;
+					var x2 = elem.getAttribute('x2')-0;
+					var y1 = elem.getAttribute('y1')-0;
+					var y2 = elem.getAttribute('y2')-0;
+					var id = elem.id;
+					
+					var mid_pt = (' '+((x1+x2)/2)+','+((y1+y2)/2) + ' ');
+					var pline = addElem({
+						"element": "polyline",
+						"attr": {
+							"points": (x1+','+y1+ mid_pt +x2+','+y2),
+							"stroke": elem.getAttribute('stroke'),
+							"stroke-width": elem.getAttribute('stroke-width'),
+							"marker-mid": mid,
+							"fill": "none",
+							"opacity": elem.getAttribute('opacity') || 1
+						}
+					});
+					$(elem).after(pline).remove();
+					svgCanvas.clearSelection();
+					pline.id = id;
+					svgCanvas.addToSelection([pline]);
+					elem = pline;
+				}
+			}
+			// Update line if it's a connector
+			if(elem.getAttribute('class') == conn_sel.substr(1)) {
+				var start = getElem($(elem).data('c_start'));
+				updateConnectors([start]);
+			} else {
+				updateConnectors();
+			}
+		},
+		toolButtonStateUpdate: function(opts) {
+			if(opts.nostroke) {
+				if ($('#mode_connect').hasClass('tool_button_current')) {
+					clickSelect();
+				}
+			}
+			$('#mode_connect')
+				.toggleClass('disabled',opts.nostroke);
+		}
+	};
+});

+ 101 - 0
main/inc/lib/svg-edit/extensions/ext-eyedropper.js

@@ -0,0 +1,101 @@
+/*
+ * ext-eyedropper.js
+ *
+ * Licensed under the Apache License, Version 2
+ *
+ * Copyright(c) 2010 Jeff Schiller
+ *
+ */
+
+svgEditor.addExtension("eyedropper", function(S) {
+		var svgcontent = S.svgcontent,
+			svgns = "http://www.w3.org/2000/svg",
+			svgdoc = S.svgroot.parentNode.ownerDocument,
+			ChangeElementCommand = svgCanvas.getPrivateMethods().ChangeElementCommand,
+			addToHistory = svgCanvas.getPrivateMethods().addCommandToHistory,
+			currentStyle = {fillPaint: "red", fillOpacity: 1.0,
+							strokePaint: "black", strokeOpacity: 1.0, 
+							strokeWidth: 5, strokeDashArray: null,
+							opacity: 1.0,
+							strokeLinecap: 'butt',
+							strokeLinejoin: 'miter',
+							};
+							
+		function getStyle(opts) {
+			// if we are in eyedropper mode, we don't want to disable the eye-dropper tool
+			var mode = svgCanvas.getMode();
+			if (mode == "eyedropper") return;
+
+			var elem = null;
+			var tool = $('#tool_eyedropper');
+			// enable-eye-dropper if one element is selected
+			if (opts.elems.length == 1 && opts.elems[0] && 
+				$.inArray(opts.elems[0].nodeName, ['svg', 'g', 'use']) == -1) 
+			{
+				elem = opts.elems[0];
+				tool.removeClass('disabled');
+				// grab the current style
+				currentStyle.fillPaint = elem.getAttribute("fill") || "black";
+				currentStyle.fillOpacity = elem.getAttribute("fill-opacity") || 1.0;
+				currentStyle.strokePaint = elem.getAttribute("stroke");
+				currentStyle.strokeOpacity = elem.getAttribute("stroke-opacity") || 1.0;
+				currentStyle.strokeWidth = elem.getAttribute("stroke-width");
+				currentStyle.strokeDashArray = elem.getAttribute("stroke-dasharray");
+				currentStyle.strokeLinecap = elem.getAttribute("stroke-linecap");
+				currentStyle.strokeLinejoin = elem.getAttribute("stroke-linejoin");
+				currentStyle.opacity = elem.getAttribute("opacity") || 1.0;
+			}
+			// disable eye-dropper tool
+			else {
+				tool.addClass('disabled');
+			}
+
+		}
+		
+		return {
+			name: "eyedropper",
+			svgicons: "extensions/eyedropper-icon.xml",
+			buttons: [{
+				id: "tool_eyedropper",
+				type: "mode",
+				title: "Eye Dropper Tool",
+				events: {
+					"click": function() {
+						svgCanvas.setMode("eyedropper");
+					}
+				}
+			}],
+			
+			// if we have selected an element, grab its paint and enable the eye dropper button
+			selectedChanged: getStyle,
+			elementChanged: getStyle,
+			
+			mouseDown: function(opts) {
+				var mode = svgCanvas.getMode();
+				if (mode == "eyedropper") {
+					var e = opts.event;
+					var target = e.target;
+					if ($.inArray(target.nodeName, ['svg', 'g', 'use']) == -1) {
+						var changes = {};
+
+						var change = function(elem, attrname, newvalue) {
+							changes[attrname] = elem.getAttribute(attrname);
+							elem.setAttribute(attrname, newvalue);
+						};
+						
+						if (currentStyle.fillPaint) 		change(target, "fill", currentStyle.fillPaint);
+						if (currentStyle.fillOpacity) 		change(target, "fill-opacity", currentStyle.fillOpacity);
+						if (currentStyle.strokePaint) 		change(target, "stroke", currentStyle.strokePaint);
+						if (currentStyle.strokeOpacity) 	change(target, "stroke-opacity", currentStyle.strokeOpacity);
+						if (currentStyle.strokeWidth) 		change(target, "stroke-width", currentStyle.strokeWidth);
+						if (currentStyle.strokeDashArray) 	change(target, "stroke-dasharray", currentStyle.strokeDashArray);
+						if (currentStyle.opacity) 			change(target, "opacity", currentStyle.opacity);
+						if (currentStyle.strokeLinecap) 	change(target, "stroke-linecap", currentStyle.strokeLinecap);
+						if (currentStyle.strokeLinejoin) 	change(target, "stroke-linejoin", currentStyle.strokeLinejoin);
+						
+						addToHistory(new ChangeElementCommand(target, changes));
+					}
+				}
+			},
+		};
+});

+ 277 - 0
main/inc/lib/svg-edit/extensions/ext-foreignobject.js

@@ -0,0 +1,277 @@
+/*
+ * ext-foreignobject.js
+ *
+ * Licensed under the Apache License, Version 2
+ *
+ * Copyright(c) 2010 Jacques Distler 
+ * Copyright(c) 2010 Alexis Deveria 
+ *
+ */
+
+svgEditor.addExtension("foreignObject", function(S) {
+		var svgcontent = S.svgcontent,
+			addElem = S.addSvgElementFromJson,
+			selElems,
+			svgns = "http://www.w3.org/2000/svg",
+			xlinkns = "http://www.w3.org/1999/xlink",
+			xmlns = "http://www.w3.org/XML/1998/namespace",
+			xmlnsns = "http://www.w3.org/2000/xmlns/",
+			se_ns = "http://svg-edit.googlecode.com",
+			htmlns = "http://www.w3.org/1999/xhtml",
+			mathns = "http://www.w3.org/1998/Math/MathML",
+			editingforeign = false,
+			svgdoc = S.svgroot.parentNode.ownerDocument,
+			started,
+			newFO;
+			
+			
+		var properlySourceSizeTextArea = function(){
+			// TODO: remove magic numbers here and get values from CSS
+			var height = $('#svg_source_container').height() - 80;
+			$('#svg_source_textarea').css('height', height);
+		};
+
+		function showPanel(on) {
+			var fc_rules = $('#fc_rules');
+			if(!fc_rules.length) {
+				fc_rules = $('<style id="fc_rules"><\/style>').appendTo('head');
+			} 
+			fc_rules.text(!on?"":" #tool_topath { display: none !important; }");
+			$('#foreignObject_panel').toggle(on);
+		}
+
+		function toggleSourceButtons(on) {
+			$('#tool_source_save, #tool_source_cancel').toggle(!on);
+			$('#foreign_save, #foreign_cancel').toggle(on);
+		}
+		
+			
+		// Function: setForeignString(xmlString, elt)
+		// This function sets the content of element elt to the input XML.
+		//
+		// Parameters:
+		// xmlString - The XML text.
+		// elt - the parent element to append to
+		//
+		// Returns:
+		// This function returns false if the set was unsuccessful, true otherwise.
+		function setForeignString(xmlString) {
+			var elt = selElems[0];
+			try {
+				// convert string into XML document
+				var newDoc = Utils.text2xml('<svg xmlns="'+svgns+'" xmlns:xlink="'+xlinkns+'">'+xmlString+'</svg>');
+				// run it through our sanitizer to remove anything we do not support
+				S.sanitizeSvg(newDoc.documentElement);
+				elt.parentNode.replaceChild(svgdoc.importNode(newDoc.documentElement.firstChild, true), elt);
+				S.call("changed", [elt]);
+				svgCanvas.clearSelection();
+			} catch(e) {
+				console.log(e);
+				return false;
+			}
+	
+			return true;
+		};
+
+		function showForeignEditor() {
+			var elt = selElems[0];
+			if (!elt || editingforeign) return;
+			editingforeign = true;
+			toggleSourceButtons(true);
+			elt.removeAttribute('fill');
+
+			var str = S.svgToString(elt, 0);
+			$('#svg_source_textarea').val(str);
+			$('#svg_source_editor').fadeIn();
+			properlySourceSizeTextArea();
+			$('#svg_source_textarea').focus();
+		}
+		
+		function setAttr(attr, val) {
+			svgCanvas.changeSelectedAttribute(attr, val);
+			S.call("changed", selElems);
+		}
+		
+		
+		return {
+			name: "foreignObject",
+			svgicons: "extensions/foreignobject-icons.xml",
+			buttons: [{
+				id: "tool_foreign",
+				type: "mode",
+				title: "Foreign Object Tool",
+				events: {
+					'click': function() {
+						svgCanvas.setMode('foreign')
+					}
+				}
+			},{
+				id: "edit_foreign",
+				type: "context",
+				panel: "foreignObject_panel",
+				title: "Edit ForeignObject Content",
+				events: {
+					'click': function() {
+						showForeignEditor();
+					}
+				}
+			}],
+			
+			context_tools: [{
+				type: "input",
+				panel: "foreignObject_panel",
+				title: "Change foreignObject's width",
+				id: "foreign_width",
+				label: "w",
+				size: 3,
+				events: {
+					change: function() {
+						setAttr('width', this.value);
+					}
+				}
+			},{
+				type: "input",
+				panel: "foreignObject_panel",
+				title: "Change foreignObject's height",
+				id: "foreign_height",
+				label: "h",
+				events: {
+					change: function() {
+						setAttr('height', this.value);
+					}
+				}
+			}, {
+				type: "input",
+				panel: "foreignObject_panel",
+				title: "Change foreignObject's font size",
+				id: "foreign_font_size",
+				label: "font-size",
+				size: 2,
+				defval: 16,
+				events: {
+					change: function() {
+						setAttr('font-size', this.value);
+					}
+				}
+			}
+			
+			
+			],
+			callback: function() {
+				$('#foreignObject_panel').hide();
+
+				var endChanges = function() {
+					$('#svg_source_editor').hide();
+					editingforeign = false;
+					$('#svg_source_textarea').blur();
+					toggleSourceButtons(false);
+				}
+
+				// TODO: Needs to be done after orig icon loads
+				setTimeout(function() {				
+					// Create source save/cancel buttons
+					var save = $('#tool_source_save').clone()
+						.hide().attr('id', 'foreign_save').unbind()
+						.appendTo("#tool_source_back").click(function() {
+							
+							if (!editingforeign) return;
+
+							if (!setForeignString($('#svg_source_textarea').val())) {
+								$.confirm("Errors found. Revert to original?", function(ok) {
+									if(!ok) return false;
+									endChanges();
+								});
+							} else {
+								endChanges();
+							}
+							// setSelectMode();	
+						});
+						
+					var cancel = $('#tool_source_cancel').clone()
+						.hide().attr('id', 'foreign_cancel').unbind()
+						.appendTo("#tool_source_back").click(function() {
+							endChanges();
+						});
+					
+				}, 3000);
+			},
+			mouseDown: function(opts) {
+				var e = opts.event;
+				
+				if(svgCanvas.getMode() == "foreign") {
+
+					started = true;
+					newFO = S.addSvgElementFromJson({
+						"element": "foreignObject",
+						"attr": {
+							"x": opts.start_x,
+							"y": opts.start_y,
+							"id": S.getNextId(),
+							"font-size": 16, //cur_text.font_size,
+							"width": "48",
+							"height": "20",
+							"style": "pointer-events:inherit"
+						}
+					});
+					var m = svgdoc.createElementNS(mathns, 'math');
+					m.setAttributeNS(xmlnsns, 'xmlns', mathns);
+					m.setAttribute('display', 'inline');
+					var mi = svgdoc.createElementNS(mathns, 'mi');
+					mi.setAttribute('mathvariant', 'normal');
+					mi.textContent = "\u03A6";
+					var mo = svgdoc.createElementNS(mathns, 'mo');
+					mo.textContent = "\u222A";
+					var mi2 = svgdoc.createElementNS(mathns, 'mi');
+					mi2.textContent = "\u2133";
+					m.appendChild(mi);
+					m.appendChild(mo);
+					m.appendChild(mi2);
+					newFO.appendChild(m);
+					return {
+						started: true
+					}
+				}
+			},
+			mouseUp: function(opts) {
+				var e = opts.event;
+				if(svgCanvas.getMode() == "foreign" && started) {
+					var attrs = $(newFO).attr(["width", "height"]);
+					keep = (attrs.width != 0 || attrs.height != 0);
+					svgCanvas.addToSelection([newFO], true);
+
+					return {
+						keep: keep,
+						element: newFO
+					}
+
+				}
+				
+			},
+			selectedChanged: function(opts) {
+				// Use this to update the current selected elements
+				selElems = opts.elems;
+				
+				var i = selElems.length;
+				
+				while(i--) {
+					var elem = selElems[i];
+					if(elem && elem.tagName == "foreignObject") {
+						if(opts.selectedElement && !opts.multiselected) {
+							$('#foreign_font_size').val(elem.getAttribute("font-size"));
+							$('#foreign_width').val(elem.getAttribute("width"));
+							$('#foreign_height').val(elem.getAttribute("height"));
+						
+							showPanel(true);
+						} else {
+							showPanel(false);
+						}
+					} else {
+						showPanel(false);
+					}
+				}
+			},
+			elementChanged: function(opts) {
+				var elem = opts.elems[0];
+			}
+		};
+});

+ 78 - 0
main/inc/lib/svg-edit/extensions/ext-helloworld.js

@@ -0,0 +1,78 @@
+/*
+ * ext-helloworld.js
+ *
+ * Licensed under the Apache License, Version 2
+ *
+ * Copyright(c) 2010 Alexis Deveria
+ *
+ */
+ 
+/* 
+	This is a very basic SVG-Edit extension. It adds a "Hello World" button in
+	the left panel. Clicking on the button, and then the canvas will show the
+ 	user the point on the canvas that was clicked on.
+*/
+ 
+svgEditor.addExtension("Hello World", function() {
+
+		return {
+			name: "Hello World",
+			// For more notes on how to make an icon file, see the source of
+			// the hellorworld-icon.xml
+			svgicons: "extensions/helloworld-icon.xml",
+			
+			// Multiple buttons can be added in this array
+			buttons: [{
+				// Must match the icon ID in helloworld-icon.xml
+				id: "hello_world", 
+				
+				// This indicates that the button will be added to the "mode"
+				// button panel on the left side
+				type: "mode", 
+				
+				// Tooltip text
+				title: "Say 'Hello World'", 
+				
+				// Events
+				events: {
+					'click': function() {
+						// The action taken when the button is clicked on.
+						// For "mode" buttons, any other button will 
+						// automatically be de-pressed.
+						svgCanvas.setMode("hello_world");
+					}
+				}
+			}],
+			// This is triggered when the main mouse button is pressed down 
+			// on the editor canvas (not the tool panels)
+			mouseDown: function() {
+				// Check the mode on mousedown
+				if(svgCanvas.getMode() == "hello_world") {
+				
+					// The returned object must include "started" with 
+					// a value of true in order for mouseUp to be triggered
+					return {started: true};
+				}
+			},
+			
+			// This is triggered from anywhere, but "started" must have been set
+			// to true (see above). Note that "opts" is an object with event info
+			mouseUp: function(opts) {
+				// Check the mode on mouseup
+				if(svgCanvas.getMode() == "hello_world") {
+					var zoom = svgCanvas.getZoom();
+					
+					// Get the actual coordinate by dividing by the zoom value
+					var x = opts.mouse_x / zoom;
+					var y = opts.mouse_y / zoom;
+					
+					var text = "Hello World!\n\nYou clicked here: " 
+						+ x + ", " + y;
+						
+					// Show the text using the custom alert function
+					$.alert(text);
+				}
+			}
+		};
+});
+

+ 572 - 0
main/inc/lib/svg-edit/extensions/ext-markers.js

@@ -0,0 +1,572 @@
+/*
+ * ext-markers.js
+ *
+ * Licensed under the Apache License, Version 2
+ *
+ * Copyright(c) 2010 Will Schleter 
+ *   based on ext-arrows.js by Copyright(c) 2010 Alexis Deveria
+ *
+ * This extension provides for the addition of markers to the either end
+ * or the middle of a line, polyline, path, polygon. 
+ * 
+ * Markers may be either a graphic or arbitary text
+ * 
+ * to simplify the coding and make the implementation as robust as possible,
+ * markers are not shared - every object has its own set of markers.
+ * this relationship is maintained by a naming convention between the
+ * ids of the markers and the ids of the object
+ * 
+ * The following restrictions exist for simplicty of use and programming
+ *    objects and their markers to have the same color
+ *    marker size is fixed
+ *    text marker font, size, and attributes are fixed
+ *    an application specific attribute - se_type - is added to each marker element
+ *        to store the type of marker
+ *        
+ * TODO:
+ *    remove some of the restrictions above
+ *    add option for keeping text aligned to horizontal
+ *    add support for dimension extension lines
+ *
+ */
+
+svgEditor.addExtension("Markers", function(S) {
+	var svgcontent = S.svgcontent,
+	addElem = S.addSvgElementFromJson,
+	selElems;
+
+	var mtypes = ['start','mid','end'];
+
+	var marker_prefix = 'se_marker_';
+	var id_prefix = 'mkr_';
+		
+	// note - to add additional marker types add them below with a unique id
+	// and add the associated icon(s) to marker-icons.svg
+	// the geometry is normallized to a 100x100 box with the origin at lower left
+	// Safari did not like negative values for low left of viewBox
+	// remember that the coordinate system has +y downward
+	var marker_types = {
+		nomarker: {},  
+		leftarrow:  
+			{element:'path', attr:{d:'M0,50 L100,90 L70,50 L100,10 Z'}},
+		rightarrow:
+			{element:'path', attr:{d:'M100,50 L0,90 L30,50 L0,10 Z'}},
+		textmarker:
+			{element:'text', attr: {x:0, y:0,'stroke-width':0,'stroke':'none','font-size':75,'font-family':'serif','text-anchor':'left',
+				'xml:space': 'preserve'}},
+		forwardslash:
+			{element:'path', attr:{d:'M30,100 L70,0'}},
+		reverseslash:
+			{element:'path', attr:{d:'M30,0 L70,100'}},
+		verticalslash:
+			{element:'path', attr:{d:'M50,0 L50,100'}},
+		box:
+			{element:'path', attr:{d:'M20,20 L20,80 L80,80 L80,20 Z'}},
+		star:
+			{element:'path', attr:{d:'M10,30 L90,30 L20,90 L50,10 L80,90 Z'}},
+		xmark:
+			{element:'path', attr:{d:'M20,80 L80,20 M80,80 L20,20'}},
+		triangle:
+			{element:'path', attr:{d:'M10,80 L50,20 L80,80 Z'}},
+		mcircle:
+			{element:'circle', attr:{r:30, cx:50, cy:50}},			
+	}
+	
+	
+	var lang_list = {
+		"en":[
+			{id: "start_marker_list", title: "Select start marker type" },
+			{id: "mid_marker_list", title: "Select mid marker type" },
+			{id: "end_marker_list", title: "Select end marker type" },
+			{id: "nomarker", title: "No Marker" },
+			{id: "leftarrow", title: "Left Arrow" },
+			{id: "rightarrow", title: "Right Arrow" },
+			{id: "textmarker", title: "Text Marker" },
+			{id: "forwardslash", title: "Forward Slash" },
+			{id: "reverseslash", title: "Reverse Slash" },
+			{id: "verticalslash", title: "Vertical Slash" },
+			{id: "box", title: "Box" },
+			{id: "star", title: "Star" },
+			{id: "xmark", title: "X" },
+			{id: "triangle", title: "Triangle" },
+			{id: "mcircle", title: "Circle" },
+			{id: "leftarrow_o", title: "Open Left Arrow" },
+			{id: "rightarrow_o", title: "Open Right Arrow" },
+			{id: "box_o", title: "Open Box" },
+			{id: "star_o", title: "Open Star" },
+			{id: "triangle_o", title: "Open Triangle" },
+			{id: "mcircle_o", title: "Open Circle" },
+		]
+	};
+
+
+	// duplicate shapes to support unfilled (open) marker types with an _o suffix
+	$.each(['leftarrow','rightarrow','box','star','mcircle','triangle'],function(i,v) {
+		marker_types[v+'_o'] = marker_types[v];
+	});
+	
+	// elem = a graphic element will have an attribute like marker-start
+	// attr - marker-start, marker-mid, or marker-end
+	// returns the marker element that is linked to the graphic element
+	function getLinked(elem, attr) {
+		var str = elem.getAttribute(attr);
+		if(!str) return null;
+		var m = str.match(/\(\#(.*)\)/);
+		if(!m || m.length !== 2) {
+			return null;
+		}
+		return S.getElem(m[1]);
+	}
+
+	//toggles context tool panel off/on
+	//sets the controls with the selected element's settings
+	function showPanel(on) {
+		$('#marker_panel').toggle(on);
+
+		if(on) {
+			var el = selElems[0];
+			var val;
+			var ci;
+
+			$.each(mtypes, function(i, pos) {
+				var m=getLinked(el,"marker-"+pos);
+				var txtbox = $('#'+pos+'_marker');
+				if (!m) {
+					val='\\nomarker';
+					ci=val;
+					txtbox.hide() // hide text box
+				} else {
+					if (!m.attributes.se_type) return; // not created by this extension
+					val='\\'+m.attributes.se_type.textContent;
+					ci=val;
+					if (val=='\\textmarker') {
+						val=m.lastChild.textContent;
+						//txtbox.show(); // show text box
+					} else {
+						txtbox.hide() // hide text box
+					}
+				}
+				txtbox.val(val);				
+				setIcon(pos,ci);
+			})
+		}
+	}	
+
+	function addMarker(id, val) {
+		var txt_box_bg = '#ffffff';
+		var txt_box_border = 'none';
+		var txt_box_stroke_width = 0;
+		
+		var marker = S.getElem(id);
+
+		if (marker) return;
+
+		if (val=='' || val=='\\nomarker') return;
+
+		var el = selElems[0];		 
+		var color = el.getAttribute('stroke');
+		//NOTE: Safari didn't like a negative value in viewBox
+		//so we use a standardized 0 0 100 100
+		//with 50 50 being mapped to the marker position
+		var refX = 50;
+		var refY = 50;
+		var viewBox = "0 0 100 100";
+		var markerWidth = 5;
+		var markerHeight = 5;
+		var strokeWidth = 10;
+		if (val.substr(0,1)=='\\') se_type=val.substr(1);
+		else se_type='textmarker';
+
+		if (!marker_types[se_type]) return; // an unknown type!
+		
+ 		// create a generic marker
+		marker = addElem({
+			"element": "marker",
+			"attr": {
+			"id": id,
+			"markerUnits": "strokeWidth",
+			"orient": "auto",
+			"style": "pointer-events:none",
+			"se_type": se_type
+		}
+		});
+
+		if (se_type!='textmarker') {
+			var mel = addElem(marker_types[se_type]);
+			var fillcolor = color;
+			if (se_type.substr(-2)=='_o') fillcolor='none';
+			mel.setAttribute('fill',fillcolor);
+			mel.setAttribute('stroke',color);
+			mel.setAttribute('stroke-width',strokeWidth);
+			marker.appendChild(mel);
+		} else {
+			var text = addElem(marker_types[se_type]);
+			// have to add text to get bounding box
+			text.textContent = val;
+			var tb=text.getBBox();
+			//alert( tb.x + " " + tb.y + " " + tb.width + " " + tb.height);
+			var pad=1;
+			var bb = tb;
+			bb.x = 0;
+			bb.y = 0;
+			bb.width += pad*2;
+			bb.height += pad*2;
+			// shift text according to its size
+			text.setAttribute('x', pad);
+			text.setAttribute('y', bb.height - pad - tb.height/4); // kludge?
+			text.setAttribute('fill',color);
+			refX = bb.width/2+pad;
+			refY = bb.height/2+pad;
+			viewBox = bb.x + " " + bb.y + " " + bb.width + " " + bb.height;
+			markerWidth =bb.width/10;
+			markerHeight = bb.height/10;
+
+			var box = addElem({
+				"element": "rect",
+				"attr": {
+				"x": bb.x,
+				"y": bb.y,
+				"width": bb.width,
+				"height": bb.height,
+				"fill": txt_box_bg,
+				"stroke": txt_box_border,
+				"stroke-width": txt_box_stroke_width
+			}
+			});
+			marker.setAttribute("orient",0);
+			marker.appendChild(box);
+			marker.appendChild(text);
+		} 
+
+		marker.setAttribute("viewBox",viewBox);
+		marker.setAttribute("markerWidth", markerWidth);
+		marker.setAttribute("markerHeight", markerHeight);
+		marker.setAttribute("refX", refX);
+		marker.setAttribute("refY", refY);
+		S.findDefs().appendChild(marker);
+
+		return marker;
+	}
+
+
+	function setMarker() {
+		var poslist={'start_marker':'start','mid_marker':'mid','end_marker':'end'};
+		var pos = poslist[this.id];
+		var marker_name = 'marker-'+pos;
+		var val = this.value;
+		var el = selElems[0];
+		var marker = getLinked(el, marker_name);
+		if (marker) $(marker).remove();
+		el.removeAttribute(marker_name);
+		if (val=='') val='\\nomarker';
+		if (val=='\\nomarker') {
+			setIcon(pos,val);
+			S.call("changed", selElems);
+			return;
+		}
+		// Set marker on element
+		var id = marker_prefix + pos + '_' + el.id;
+		addMarker(id, val);
+		svgCanvas.changeSelectedAttribute(marker_name, "url(#" + id + ")");
+		if (el.tagName == "line" && pos=='mid') el=convertline(el);
+		S.call("changed", selElems);
+		setIcon(pos,val);
+	}
+
+	function convertline(elem) {
+		// this routine came from the connectors extension
+		// it is needed because midpoint markers don't work with line elements
+		if (!(elem.tagName == "line")) return elem;
+
+		// Convert to polyline to accept mid-arrow
+
+		var x1 = elem.getAttribute('x1')-0;
+		var x2 = elem.getAttribute('x2')-0;
+		var y1 = elem.getAttribute('y1')-0;
+		var y2 = elem.getAttribute('y2')-0;
+		var id = elem.id;
+
+		var mid_pt = (' '+((x1+x2)/2)+','+((y1+y2)/2) + ' ');
+		var pline = addElem({
+			"element": "polyline",
+			"attr": {
+			"points": (x1+','+y1+ mid_pt +x2+','+y2),
+			"stroke": elem.getAttribute('stroke'),
+			"stroke-width": elem.getAttribute('stroke-width'),
+			"fill": "none",
+			"opacity": elem.getAttribute('opacity') || 1
+		}
+		});
+		$.each(mtypes, function(i, pos) { // get any existing marker definitions
+			var nam = 'marker-'+pos;
+			var m = elem.getAttribute(nam);
+			if (m) pline.setAttribute(nam,elem.getAttribute(nam));
+		});
+		
+		var batchCmd = new S.BatchCommand();
+		batchCmd.addSubCommand(new S.RemoveElementCommand(elem, elem.parentNode));
+		batchCmd.addSubCommand(new S.InsertElementCommand(pline));
+		
+		$(elem).after(pline).remove();
+		svgCanvas.clearSelection();
+		pline.id = id;
+		svgCanvas.addToSelection([pline]);
+		S.addCommandToHistory(batchCmd);
+		return pline;
+	}
+
+	// called when the main system modifies an object
+	// this routine changes the associated markers to be the same color
+	function colorChanged(elem) {
+		var color = elem.getAttribute('stroke');
+
+		$.each(mtypes, function(i, pos) {
+			var marker = getLinked(elem, 'marker-'+pos);
+			if (!marker) return;
+			if (!marker.attributes.se_type) return; //not created by this extension
+			var ch = marker.lastElementChild;
+			if (!ch) return;
+			var curfill = ch.getAttribute("fill");
+			var curstroke = ch.getAttribute("stroke")
+			if (curfill && curfill!='none') ch.setAttribute("fill",color);
+			if (curstroke && curstroke!='none') ch.setAttribute("stroke",color);
+		});
+	}
+
+	// called when the main system creates or modifies an object
+	// primary purpose is create new markers for cloned objects
+	function updateReferences(el) {
+		$.each(mtypes, function (i,pos) {
+			var id = marker_prefix + pos + '_' + el.id;
+			var marker_name = 'marker-'+pos;
+			var marker = getLinked(el, marker_name);
+			if (!marker || !marker.attributes.se_type) return; //not created by this extension
+			var url = el.getAttribute(marker_name);
+			if (url) {
+				var len = el.id.length;
+				var linkid = url.substr(-len-1,len);
+				if (el.id != linkid) {
+					var val = $('#'+pos+'_marker').attr('value');
+					addMarker(id, val);
+					svgCanvas.changeSelectedAttribute(marker_name, "url(#" + id + ")");
+					if (el.tagName == "line" && pos=='mid') el=convertline(el);
+					S.call("changed", selElems);
+				}
+			}
+		});
+	}
+
+	// simulate a change event a text box that stores the current element's marker type
+	function triggerTextEntry(pos,val) {
+		$('#'+pos+'_marker').val(val);
+		$('#'+pos+'_marker').change();
+		var txtbox = $('#'+pos+'_marker');
+		//if (val.substr(0,1)=='\\') txtbox.hide();
+		//else txtbox.show();
+	}
+	
+	function setIcon(pos,id) {
+		if (id.substr(0,1)!='\\') id='\\textmarker'
+		var ci = '#'+id_prefix+pos+'_'+id.substr(1);
+		svgEditor.setIcon('#cur_' + pos +'_marker_list', $(ci).children());
+		$(ci).addClass('current').siblings().removeClass('current');
+	}
+		
+	function setMarkerSet(obj) {
+		var parts = this.id.split('_');
+		var set = parts[2];
+		switch (set) {
+		case 'off':
+			triggerTextEntry('start','\\nomarker');
+			triggerTextEntry('mid','\\nomarker');
+			triggerTextEntry('end','\\nomarker');
+			break;
+		case 'dimension':
+			triggerTextEntry('start','\\leftarrow');
+			triggerTextEntry('end','\\rightarrow');
+			showTextPrompt('mid');
+			break;
+		case 'label':
+			triggerTextEntry('mid','\\nomarker');
+			triggerTextEntry('end','\\rightarrow');
+			showTextPrompt('start');
+			break;
+		}
+	}
+		
+	function showTextPrompt(pos) {
+		var def = $('#'+pos+'_marker').val();
+		if (def.substr(0,1)=='\\') def='';
+		$.prompt('Enter text for ' + pos + ' marker', def , function(txt) { if (txt) triggerTextEntry(pos,txt); });
+	}
+	
+	// callback function for a toolbar button click
+	function setArrowFromButton(obj) {
+		
+		var parts = this.id.split('_');
+		var pos = parts[1];
+		var val = parts[2];
+		if (parts[3]) val+='_'+parts[3];
+		
+		if (val!='textmarker') {
+			triggerTextEntry(pos,'\\'+val);
+		} else {
+			showTextPrompt(pos);
+		}
+	}
+	
+	function getTitle(lang,id) {
+		var list = lang_list[lang];
+		for (var i in list) {
+			if (list[i].id==id) return list[i].title;
+		}
+		return id;
+	}
+	
+	
+	// build the toolbar button array from the marker definitions
+	// TODO: need to incorporate language specific titles
+	function buildButtonList() {
+		var buttons=[];
+		var i=0;
+/*
+		buttons.push({
+			id:id_prefix + 'markers_off',
+			title:'Turn off all markers',
+			type:'context',
+			events: { 'click': setMarkerSet },
+			panel: 'marker_panel'
+		});
+		buttons.push({
+			id:id_prefix + 'markers_dimension',
+			title:'Dimension',
+			type:'context',
+			events: { 'click': setMarkerSet },
+			panel: 'marker_panel'
+		});
+		buttons.push({
+			id:id_prefix + 'markers_label',
+			title:'Label',
+			type:'context',
+			events: { 'click': setMarkerSet },
+			panel: 'marker_panel'
+		});
+*/
+		$.each(mtypes,function(k,pos) {
+			var listname = pos + "_marker_list";
+			var def = true;
+		$.each(marker_types,function(id,v) {
+			var title = getTitle('en',id);
+			buttons.push({
+					id:id_prefix + pos + "_" + id,
+					svgicon:id,
+					title:title,
+					type:'context',
+					events: { 'click': setArrowFromButton },
+					panel:'marker_panel',
+					list: listname,
+					isDefault: def
+			});
+			def = false;
+		});
+		});
+		return buttons;
+	}
+
+	return {
+		name: "Markers",
+		svgicons: "extensions/markers-icons.xml",
+		buttons: buildButtonList(),
+		context_tools: [
+		   {
+			type: "input",
+			panel: "marker_panel",
+			title: "Start marker",
+			id: "start_marker",
+			label: "s",
+			size: 3,
+			events: { change: setMarker }
+		},{
+			type: "button-select",
+			panel: "marker_panel",
+			title: getTitle('en','start_marker_list'),
+			id: "start_marker_list",
+			colnum: 3,
+			events: { change: setArrowFromButton }
+		},{
+			type: "input",
+			panel: "marker_panel",
+			title: "Middle marker",
+			id: "mid_marker",
+			label: "m",
+			defval: "",
+			size: 3,
+			events: { change: setMarker }
+		},{
+			type: "button-select",
+			panel: "marker_panel",
+			title: getTitle('en','mid_marker_list'),
+			id: "mid_marker_list",
+			colnum: 3,
+			events: { change: setArrowFromButton }
+		},{
+			type: "input",
+			panel: "marker_panel",
+			title: "End marker",
+			id: "end_marker",
+			label: "e",
+			size: 3,
+			events: { change: setMarker }
+		},{
+			type: "button-select",
+			panel: "marker_panel",
+			title: getTitle('en','end_marker_list'),
+			id: "end_marker_list",
+			colnum: 3,
+			events: { change: setArrowFromButton }
+		} ],
+		callback: function() {
+			$('#marker_panel').addClass('toolset').hide();
+			
+		},
+		addLangData: function(lang) {
+			return { data: lang_list[lang] };
+		},
+
+	selectedChanged: function(opts) {
+		// Use this to update the current selected elements
+		//console.log('selectChanged',opts);
+		selElems = opts.elems;
+
+		var i = selElems.length;
+		var marker_elems = ['line','path','polyline','polygon'];
+
+		while(i--) {
+			var elem = selElems[i];
+			if(elem && $.inArray(elem.tagName, marker_elems) != -1) {
+				if(opts.selectedElement && !opts.multiselected) {
+					showPanel(true);
+				} else {
+					showPanel(false);
+				}
+			} else {
+				showPanel(false);
+			}
+		}
+	},
+
+	elementChanged: function(opts) {		
+		//console.log('elementChanged',opts);
+		var elem = opts.elems[0];
+		if(elem && (
+				elem.getAttribute("marker-start") ||
+				elem.getAttribute("marker-mid") ||
+				elem.getAttribute("marker-end")
+		)) {
+			colorChanged(elem);
+			updateReferences(elem);
+		}
+		changing_flag = false;
+	}
+	};
+});

+ 179 - 0
main/inc/lib/svg-edit/extensions/ext-server_opensave.js

@@ -0,0 +1,179 @@
+/*
+ * ext-server_opensave.js
+ *
+ * Licensed under the Apache License, Version 2
+ *
+ * Copyright(c) 2010 Alexis Deveria
+ *
+ */
+
+svgEditor.addExtension("server_opensave", {
+	callback: function() {
+
+		var save_svg_action = 'extensions/filesave.php';
+		var save_png_action = 'extensions/filesave.php';
+	
+		// Create upload target (hidden iframe)
+		var target = $('<iframe name="output_frame" src="#"/>').hide().appendTo('body');
+	
+		svgEditor.setCustomHandlers({
+			save: function(win, data) {
+				var svg = '<?xml version="1.0"?>' + data;
+				
+				var title = svgCanvas.getDocumentTitle();
+				var filename = title.replace(/[^a-z0-9\.\_\-]+/gi, '_');
+				
+				var form = $('<form>').attr({
+					method: 'post',
+					action: save_svg_action,
+					target: 'output_frame'
+				})	.append('<input type="hidden" name="output_svg" value="' + encodeURI(svg) + '">')
+					.append('<input type="hidden" name="filename" value="' + filename + '">')
+					.appendTo('body')
+					.submit().remove();
+			},
+			pngsave: function(win, data) {
+				var issues = data.issues;
+				
+				if(!$('#export_canvas').length) {
+					$('<canvas>', {id: 'export_canvas'}).hide().appendTo('body');
+				}
+				var c = $('#export_canvas')[0];
+				
+				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();
+	
+				
+			}
+		});
+	
+		// Do nothing if client support is found
+		if(window.FileReader) return;
+		
+		var cancelled = false;
+	
+		// Change these to appropriate script file
+		var open_svg_action = 'extensions/fileopen.php?type=load_svg';
+		var import_svg_action = 'extensions/fileopen.php?type=import_svg';
+		var import_img_action = 'extensions/fileopen.php?type=import_img';
+		
+		// Set up function for PHP uploader to use
+		svgEditor.processFile = function(str64, type) {
+			if(cancelled) {
+				cancelled = false;
+				return;
+			}
+		
+			$('#dialog_box').hide();
+		
+			if(type != 'import_img') {
+				var xmlstr = svgCanvas.Utils.decode64(str64);
+			}
+			
+			switch ( type ) {
+				case 'load_svg':
+					svgCanvas.clear();
+					svgCanvas.setSvgString(xmlstr);
+					svgEditor.updateCanvas();
+					break;
+				case 'import_svg':
+					svgCanvas.importSvgString(xmlstr);
+					svgEditor.updateCanvas();					
+					break;
+				case 'import_img':
+					svgCanvas.setGoodImage(str64);
+					break;
+			}
+		}
+	
+		// Create upload form
+		var open_svg_form = $('<form>');
+		open_svg_form.attr({
+			enctype: 'multipart/form-data',
+			method: 'post',
+			action: open_svg_action,
+			target: 'output_frame'
+		});
+		
+		// Create import form
+		var import_svg_form = open_svg_form.clone().attr('action', import_svg_action);
+		
+		// Create image form
+		var import_img_form = open_svg_form.clone().attr('action', import_img_action);
+		
+		// It appears necessory to rebuild this input every time a file is 
+		// selected so the same file can be picked and the change event can fire.
+		function rebuildInput(form) {
+			form.empty();
+			var inp = $('<input type="file" name="svg_file">').appendTo(form);
+			
+			
+			function submit() {
+				// This submits the form, which returns the file data using svgEditor.uploadSVG
+				form.submit();
+				
+				rebuildInput(form);
+				$.process_cancel("Uploading...", function() {
+					cancelled = true;
+					$('#dialog_box').hide();
+				});
+			}
+			
+			if(form[0] == open_svg_form[0]) {
+				inp.change(function() {
+					// This takes care of the "are you sure" dialog box
+					svgEditor.openPrep(function(ok) {
+						if(!ok) {
+							rebuildInput(form);
+							return;
+						}
+						submit();
+					});
+				});
+			} else {
+				inp.change(function() {
+					// This submits the form, which returns the file data using svgEditor.uploadSVG
+					submit();
+				});
+			}
+		}
+		
+		// Create the input elements
+		rebuildInput(open_svg_form);
+		rebuildInput(import_svg_form);
+		rebuildInput(import_img_form);
+
+		// Add forms to buttons
+		$("#tool_open").show().prepend(open_svg_form);
+		$("#tool_import").show().prepend(import_svg_form);
+		$("#tool_image").prepend(import_img_form);
+	}
+});
+

+ 34 - 0
main/inc/lib/svg-edit/extensions/eyedropper-icon.xml

@@ -0,0 +1,34 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+
+<g id="tool_eyedropper">
+<svg viewBox="0 0 320 320" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <!-- Created with SVG-edit - http://svg-edit.googlecode.com/ -->
+ <defs>
+  <radialGradient id="eyedropper_svg_6" cx="0.5" cy="0.5" r="0.5">
+   <stop offset="0" stop-color="#ffffff" stop-opacity="1"/>
+   <stop offset="1" stop-color="#e5e5e5" stop-opacity="0.38"/>
+  </radialGradient>
+  <linearGradient id="eyedropper_svg_15" x1="0" y1="0" x2="0.58594" y2="0.55078">
+   <stop offset="0" stop-color="#ffffff" stop-opacity="0.57"/>
+   <stop offset="1" stop-color="#000056" stop-opacity="1"/>
+  </linearGradient>
+  <linearGradient id="eyedropper_svg_19" x1="0" y1="0" x2="1" y2="1">
+   <stop offset="0" stop-color="#ffffff" stop-opacity="1"/>
+   <stop offset="1" stop-color="#ffffff" stop-opacity="0"/>
+  </linearGradient>
+ </defs>
+ <g display="inline">
+  <title>Layer 1</title>
+  <path d="m193.899994,73l-119.899979,118l-15,39.5l10.25,4.5l43.750015,-20l108.999969,-112l-28.100006,-30z" id="svg_3" fill="none" stroke="#000000" stroke-width="5"/>
+  <path d="m58.649994,232c-2.75,28.200012 -26.399994,28.950012 -21.899994,59c4.5,30.049988 55,28 55.5,-1.25c0.5,-29.25 -20.25,-28.75 -22.25,-54.75l-11.350006,-3z" id="svg_4" fill="#aa56ff" stroke="#000000" stroke-width="7"/>
+  <path d="m45.474976,269.275024l13.775024,0.474976l-0.75,16.75l-14.25,-1.25l1.224976,-15.974976z" id="svg_5" fill="url(#eyedropper_svg_6)" stroke-width="5" fill-opacity="0.73"/>
+  <path d="m217.899994,46c21.5,-101.549999 141.600006,20.449997 28.100006,33l-5,44l-63,-66l39.899994,-11z" id="svg_2" fill="#000000" stroke-width="5"/>
+  <path d="m206.825012,61.075008c3.712494,-2.46249 7.637482,-3.53751 14.424988,-5.575008c10.125,-16.5 32.875,-41.5 40.5,-35c7.625,6.5 -21.25,35.625 -37.5,39.25c-5.5,10.125 -8,13.875 -17.25,16.5c-2.837494,-8.162514 -4.262482,-12.337486 -0.174988,-15.174992z" id="svg_7" fill="url(#eyedropper_svg_15)" stroke-width="5"/>
+  <path d="m133.049988,134.75l46.950012,9.25l-66,70l-42.5,20.5l-11.5,-5l14,-37.5l59.049988,-57.25z" id="svg_11" fill="#aa56ff" stroke="#000000" stroke-width="7"/>
+  <path d="m71.425034,212.350006l9.050888,-20.022537l51.516724,-49.327469l8.507355,0.97197l-69.074966,68.378036z" id="svg_16" fill="url(#eyedropper_svg_19)" stroke-width="5"/>
+ </g>
+</svg>
+</g>
+	
+	<g id="svg_eof"/>
+</svg>

BIN
main/inc/lib/svg-edit/extensions/eyedropper.png


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

@@ -0,0 +1,31 @@
+<!doctype html>
+<?php
+/*
+ * fileopen.php
+ * To be used with ext-server_opensave.js for SVG-edit
+ *
+ * Licensed under the Apache License, Version 2
+ *
+ * Copyright(c) 2010 Alexis Deveria
+ *
+ */
+	// Very minimal PHP file, all we do is Base64 encode the uploaded file and
+	// return it to the editor
+	
+	$file = $_FILES['svg_file']['tmp_name'];
+	
+	$output = file_get_contents($file);
+	
+	$type = $_REQUEST['type'];
+	
+	$prefix = '';
+	
+	// Make Data URL prefix for import image
+	if($type == 'import_img') {
+		$info = getimagesize($file);
+		$prefix = 'data:' . $info['mime'] . ';base64,';
+	}
+?>
+<script>
+window.top.window.svgEditor.processFile("<?php echo $prefix . base64_encode($output); ?>", "<?php echo $type ?>");
+</script>  

+ 44 - 0
main/inc/lib/svg-edit/extensions/filesave.php

@@ -0,0 +1,44 @@
+<?php
+/*
+ * filesave.php
+ * To be used with ext-server_opensave.js for SVG-edit
+ *
+ * Licensed under the Apache License, Version 2
+ *
+ * Copyright(c) 2010 Alexis Deveria
+ *
+ */
+ 
+if(!isset($_POST['output_svg']) && !isset($_POST['output_png'])) {
+	die('post fail');
+}
+
+$file = '';
+
+$suffix = isset($_POST['output_svg'])?'.svg':'.png';
+
+if(isset($_POST['filename']) && strlen($_POST['filename']) > 0) {
+	$file = $_POST['filename'] . $suffix;
+} else {
+	$file = 'image' . $suffix;
+}
+
+if($suffix == '.svg') {
+	$mime = 'image/svg+xml';
+	$contents = rawurldecode($_POST['output_svg']);
+} else {
+	$mime = 'image/png';
+	$contents = $_POST['output_png'];
+	$pos = (strpos($contents, 'base64,') + 7);
+	$contents = base64_decode(substr($contents, $pos));
+}
+
+ header("Cache-Control: public");
+ header("Content-Description: File Transfer");
+ header("Content-Disposition: attachment; filename=" . $file);
+ header("Content-Type: " .  $mime);
+ header("Content-Transfer-Encoding: binary");
+ 
+ echo $contents;
+ 
+?>

+ 96 - 0
main/inc/lib/svg-edit/extensions/foreignobject-icons.xml

@@ -0,0 +1,96 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+	<g id="tool_foreign">
+		<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 84 84">
+		  <g fill="#444" opacity="0.2" transform="translate(6,6)">
+		  <path d="M42.8,74.3c0,4.3,0,5.9,11.8,5.9l4.1,0l0,3.8c-4.5-0.4-16.1-0.4-21.2-0.3c-5.1,0-16.6,0-21,0.4l0-3.8l4.1,0
+			c11.8,0,11.8-1.7,11.8-5.9l0-6.9C13.9,65.6,0,54.6,0,42c0-12.2,13.3-23.5,32.4-25.4l0-6.9c0-4.3,0-5.9-11.8-5.9l-4.1,0l0-3.8
+			c4.5,0.4,16.1,0.4,21.2,0.3c5.1,0,16.6,0,21-0.4l0,3.8l-4.1,0c-11.8,0-11.8,1.7-11.8,5.9l0,6.9C61.6,18.1,75.8,29.2,75.8,42
+			c0,12.4-13.8,23.9-33.1,25.4L42.8,74.3z M32.4,19.4c-18.7,2.5-19.9,16.2-19.9,22.6c0,7.6,2.3,20.2,20,22.5L32.4,19.4z M42.7,64.7
+			c18.8-2.2,20.7-15.4,20.6-22.8c0-9.3-3.5-20.6-20.7-22.6L42.7,64.7z"/>
+		  </g>
+		  <g fill="#444" opacity="0.3" transform="translate(4,4)">
+		  <path d="M42.8,74.3c0,4.3,0,5.9,11.8,5.9l4.1,0l0,3.8c-4.5-0.4-16.1-0.4-21.2-0.3c-5.1,0-16.6,0-21,0.4l0-3.8l4.1,0
+			c11.8,0,11.8-1.7,11.8-5.9l0-6.9C13.9,65.6,0,54.6,0,42c0-12.2,13.3-23.5,32.4-25.4l0-6.9c0-4.3,0-5.9-11.8-5.9l-4.1,0l0-3.8
+			c4.5,0.4,16.1,0.4,21.2,0.3c5.1,0,16.6,0,21-0.4l0,3.8l-4.1,0c-11.8,0-11.8,1.7-11.8,5.9l0,6.9C61.6,18.1,75.8,29.2,75.8,42
+			c0,12.4-13.8,23.9-33.1,25.4L42.8,74.3z M32.4,19.4c-18.7,2.5-19.9,16.2-19.9,22.6c0,7.6,2.3,20.2,20,22.5L32.4,19.4z M42.7,64.7
+			c18.8-2.2,20.7-15.4,20.6-22.8c0-9.3-3.5-20.6-20.7-22.6L42.7,64.7z"/>
+		  </g>
+		  <g fill="#444" opacity="0.5" transform="translate(2,2)">
+		  <path d="M42.8,74.3c0,4.3,0,5.9,11.8,5.9l4.1,0l0,3.8c-4.5-0.4-16.1-0.4-21.2-0.3c-5.1,0-16.6,0-21,0.4l0-3.8l4.1,0
+			c11.8,0,11.8-1.7,11.8-5.9l0-6.9C13.9,65.6,0,54.6,0,42c0-12.2,13.3-23.5,32.4-25.4l0-6.9c0-4.3,0-5.9-11.8-5.9l-4.1,0l0-3.8
+			c4.5,0.4,16.1,0.4,21.2,0.3c5.1,0,16.6,0,21-0.4l0,3.8l-4.1,0c-11.8,0-11.8,1.7-11.8,5.9l0,6.9C61.6,18.1,75.8,29.2,75.8,42
+			c0,12.4-13.8,23.9-33.1,25.4L42.8,74.3z M32.4,19.4c-18.7,2.5-19.9,16.2-19.9,22.6c0,7.6,2.3,20.2,20,22.5L32.4,19.4z M42.7,64.7
+			c18.8-2.2,20.7-15.4,20.6-22.8c0-9.3-3.5-20.6-20.7-22.6L42.7,64.7z"/>
+		  </g>
+		  <g fill="#0000CC">
+		  <path id="xyz321" d="M42.8,74.3c0,4.3,0,5.9,11.8,5.9l4.1,0l0,3.8c-4.5-0.4-16.1-0.4-21.2-0.3c-5.1,0-16.6,0-21,0.4l0-3.8l4.1,0
+			c11.8,0,11.8-1.7,11.8-5.9l0-6.9C13.9,65.6,0,54.6,0,42c0-12.2,13.3-23.5,32.4-25.4l0-6.9c0-4.3,0-5.9-11.8-5.9l-4.1,0l0-3.8
+			c4.5,0.4,16.1,0.4,21.2,0.3c5.1,0,16.6,0,21-0.4l0,3.8l-4.1,0c-11.8,0-11.8,1.7-11.8,5.9l0,6.9C61.6,18.1,75.8,29.2,75.8,42
+			c0,12.4-13.8,23.9-33.1,25.4L42.8,74.3z M32.4,19.4c-18.7,2.5-19.9,16.2-19.9,22.6c0,7.6,2.3,20.2,20,22.5L32.4,19.4z M42.7,64.7
+			c18.8-2.2,20.7-15.4,20.6-22.8c0-9.3-3.5-20.6-20.7-22.6L42.7,64.7z"/>
+		  </g>
+		</svg>
+	</g>
+	
+	<g id="edit_foreign">
+		<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="34 38 170 170" overflow="hidden">
+		<g fill="#000088">
+			<path d="M30.1,63.9v-4.3l30.2-14.9V50L36.5,61.7l23.8,11.7v5.3L30.1,63.9z"/>
+			<path d="M106.1,79.7v-1.1c4.2-0.5,4.8-1.1,4.8-5.2V58.2c0-6-1.3-7.9-5.4-7.9c-3.3,0-5.7,1.3-7.8,4.4v18.1
+				c0,4.5,1.1,5.7,5.2,5.8v1.1H86.8v-1.1c4.1-0.3,4.9-1.1,4.9-5.1V57.9c0-5-1.6-7.6-4.8-7.6c-2.5,0-5.6,1.2-7.4,2.9
+				c-0.5,0.5-1.1,1.4-1.1,1.4v20.3c0,2.8,1.1,3.6,4.9,3.7v1.1h-16v-1.1c4-0.1,5-1.2,5-5V55.4c0-3.5-0.6-4.6-2.5-4.6
+				c-0.8,0-1.4,0.1-2.3,0.3v-1.2c4-1.1,6.4-1.9,10.1-3.2l0.5,0.1v5.4c6-4.5,8-5.5,11.2-5.5c3.9,0,6.3,1.9,7.6,6c3.9-4.2,7.6-6,11.7-6
+				c5.5,0,8.4,4.3,8.4,12.8v14.8c0,2.8,0.9,4.1,3.1,4.2l1.9,0.1v1.1H106.1z"/>
+			<path d="M147.3,80.5c-3,0-4.2-1.4-4.6-5.3c-4.4,3.7-7.3,5.3-10.5,5.3c-4.5,0-7.6-3.2-7.6-7.7c0-2.4,1-4.8,2.6-6.3
+				c3.1-2.7,4.3-3.3,15.4-7.8v-4.4c0-3.9-1.9-6-5.5-6c-2.9,0-5.2,1.6-5.2,3.5c0,0.5,0.1,1.1,0.2,1.7c0.1,0.5,0.1,0.9,0.1,1.2
+				c0,1.6-1.5,3-3.2,3s-3.1-1.4-3.1-3.1c0-1.8,1.2-3.9,3-5.4c2-1.7,5.5-2.7,9.1-2.7c4.4,0,7.5,1.4,9,4.2c1,1.7,1.4,3.7,1.4,7.3v14
+				c0,3.2,0.5,4.2,2.2,4.2c1.1,0,1.9-0.4,3.2-1.4v1.9C151.3,79.6,149.8,80.5,147.3,80.5z M142.6,60.5c-8.7,3.2-11.7,5.8-11.7,10v0.3
+				c0,3.1,2,5.5,4.5,5.5c1.5,0,3.5-0.6,5.3-1.6c1.5-0.9,1.9-1.6,1.9-3.8V60.5z"/>
+			<path d="M165.3,80.5c-4.2,0-6.3-3.1-6.3-9.1V49.7h-3.8c-0.2-0.1-0.3-0.3-0.3-0.5c0-0.4,0.4-0.9,1.2-1.4
+				c1.9-1.1,4.3-3.7,7-7.7c0.5-0.6,1-1.3,1.4-2c0.4,0,0.5,0.2,0.5,0.9v8.4h7.3v2.3h-7.3v20.6c0,4.6,1.1,6.5,3.7,6.5
+				c1.6,0,2.7-0.6,4.3-2.5l0.9,0.8C171.8,78.7,169,80.5,165.3,80.5z"/>
+			<path d="M193.8,79.7v-1.1c4.1-0.4,4.9-1.3,4.9-6.2V58.1c0-5-1.8-7.6-5.4-7.6c-2.8,0-5,1.2-8,4.5v17.4
+				c0,5,0.7,5.8,4.9,6.3v1.1h-15.6v-1.1c4.2-0.6,4.6-1.2,4.6-6.3V38.5c0-3.1-0.6-3.7-3.7-3.7c-0.4,0-0.6,0-0.9,0.1v-1.2l1.9-0.6
+				c4-1.2,5.8-1.7,8.3-2.6l0.4,0.2v21.9c3.3-4.3,6.3-6,10.6-6c5.9,0,8.9,3.9,8.9,11.5v14.3c0,5,0.4,5.5,4.3,6.3v1.1h-15.2V79.7z"/>
+			<path d="M59.1,116.1v-4.3l30.2-14.9v5.3l-23.8,11.7l23.8,11.7v5.3L59.1,116.1z"/>
+			<path d="M135.1,131.9v-1.1c4.2-0.5,4.8-1.1,4.8-5.2v-15.1c0-6-1.3-7.9-5.4-7.9c-3.3,0-5.7,1.3-7.8,4.4v18.1
+				c0,4.5,1.1,5.7,5.2,5.8v1.1h-16.1v-1.1c4.1-0.3,4.9-1.1,4.9-5.1v-15.7c0-5-1.6-7.6-4.8-7.6c-2.5,0-5.6,1.2-7.4,2.9
+				c-0.5,0.5-1.1,1.4-1.1,1.4v20.3c0,2.8,1.1,3.6,4.9,3.7v1.1h-16v-1.1c4-0.1,5-1.2,5-5v-18.2c0-3.5-0.6-4.6-2.5-4.6
+				c-0.8,0-1.4,0.1-2.3,0.3v-1.2c4-1.1,6.4-1.9,10.1-3.2l0.5,0.1v5.4c6-4.5,8-5.5,11.2-5.5c3.9,0,6.3,1.9,7.6,6c3.9-4.2,7.6-6,11.7-6
+				c5.5,0,8.4,4.3,8.4,12.8v14.8c0,2.8,0.9,4.1,3.1,4.2l1.9,0.1v1.1H135.1z"/>
+			<path d="M152.1,131.9v-1.1c5-0.3,5.7-1.1,5.7-6.3v-16.6c0-3.2-0.6-4.3-2.4-4.3c-0.6,0-1.6,0.1-2.4,0.2l-0.6,0.1v-1.1
+				l11.2-4L164,99v25.6c0,5.2,0.6,5.9,5.3,6.3v1.1L152.1,131.9L152.1,131.9z M160.8,93.1c-2,0-3.7-1.6-3.7-3.7c0-2,1.7-3.7,3.7-3.7
+				c2.1,0,3.7,1.7,3.7,3.7C164.6,91.6,163,93.1,160.8,93.1z"/>
+			<path d="M175.8,131v-5.3l23.7-11.8l-23.7-11.7v-5.3l30.1,14.9v4.3L175.8,131z"/>
+			<path d="M31.1,169.5v-4.3l30.2-14.9v5.3l-23.8,11.7L61.3,179v5.3L31.1,169.5z"/>
+			<path d="M71.3,186.4h-4.9l16.5-49.7h4.8L71.3,186.4z"/>
+			<path d="M127.1,185.3v-1.1c4.2-0.5,4.8-1.1,4.8-5.2v-15.2c0-6-1.3-7.9-5.4-7.9c-3.3,0-5.7,1.3-7.8,4.4v18.1
+				c0,4.5,1.1,5.7,5.2,5.8v1.1h-16.1v-1.1c4.1-0.3,4.9-1.1,4.9-5.1v-15.6c0-5-1.6-7.6-4.8-7.6c-2.5,0-5.6,1.2-7.4,2.9
+				c-0.5,0.5-1.1,1.4-1.1,1.4v20.3c0,2.8,1.1,3.6,4.9,3.7v1.1h-16v-1.1c4-0.1,5-1.2,5-5V161c0-3.5-0.6-4.6-2.5-4.6
+				c-0.8,0-1.4,0.1-2.3,0.3v-1.2c4-1.1,6.4-1.9,10.1-3.2l0.5,0.1v5.4c6-4.5,8-5.5,11.2-5.5c3.9,0,6.3,1.9,7.6,6c3.9-4.2,7.6-6,11.7-6
+				c5.5,0,8.4,4.3,8.4,12.8v14.8c0,2.8,0.9,4.1,3.1,4.2l1.9,0.1v1.1H127.1L127.1,185.3z"/>
+			<path d="M168.3,186.1c-3,0-4.2-1.4-4.6-5.3c-4.4,3.7-7.3,5.3-10.5,5.3c-4.5,0-7.6-3.2-7.6-7.7c0-2.4,1-4.8,2.6-6.3
+				c3.1-2.7,4.3-3.3,15.4-7.8v-4.4c0-3.9-1.9-6-5.5-6c-2.9,0-5.2,1.6-5.2,3.5c0,0.5,0.1,1.1,0.2,1.7c0.1,0.5,0.1,0.9,0.1,1.2
+				c0,1.6-1.5,3-3.2,3s-3.1-1.4-3.1-3.1c0-1.8,1.2-3.9,3-5.4c2-1.7,5.5-2.7,9.1-2.7c4.4,0,7.5,1.4,9,4.2c1,1.7,1.4,3.7,1.4,7.3v14
+				c0,3.2,0.5,4.2,2.2,4.2c1.1,0,1.9-0.4,3.2-1.4v1.9C172.3,185.2,170.8,186.1,168.3,186.1z M163.8,166.1c-8.7,3.2-11.7,5.8-11.7,10
+				v0.3c0,3.1,2,5.5,4.5,5.5c1.5,0,3.5-0.6,5.3-1.6c1.5-0.9,1.9-1.6,1.9-3.8V166.1z"/>
+			<path d="M186.3,186.1c-4.2,0-6.3-3.1-6.3-9.1v-21.7h-3.8c-0.2-0.1-0.3-0.3-0.3-0.5c0-0.4,0.4-0.9,1.2-1.4
+				c1.9-1.1,4.3-3.7,7-7.7c0.5-0.6,1-1.3,1.4-2c0.4,0,0.5,0.2,0.5,0.9v8.4h7.3v2.3h-7.3v20.6c0,4.6,1.1,6.5,3.7,6.5
+				c1.6,0,2.7-0.6,4.3-2.5l0.9,0.8C192.8,184.3,190,186.1,186.3,186.1z"/>
+			<path d="M209.1,185.3h-13.4v-1.1c4.2-0.6,4.6-1.2,4.6-6.3V144c0-3.1-0.6-3.7-3.7-3.7c-0.4,0-0.6,0-0.9,0.1v-1.2
+				l1.9-0.6c4-1.2,5.8-1.7,8.3-2.6l0.4,0.2v21.9c0.9-1.2,1.9-2.2,2.8-3.1"/>
+			<path d="M209.1,157.9c-0.8,0.7-1.7,1.5-2.7,2.6v17.4c0,4,0.4,5.3,2.7,5.9"/>
+		  </g>
+		  <g>
+			<polyline opacity="0.2" fill="#231F20" points="209.1,76.4 118.7,186.5 139.1,186.4 209.1,121 209.1,76.4 "/>
+			<polyline opacity="0.4" fill="#231F20" points="209.1,76.2 118.5,186.5 129.7,186.4 200.2,120.3 209.1,100.8 209.1,76.4 "/>
+			<path fill="#FFD761" d="M121.6,88.7l0.8,87.5l62.3-56.7c0,0-15.3-25.8-24.8-30C151.1,85.6,121.6,88.7,121.6,88.7z"/>
+			<path fill="#FEA01E" d="M209.1,19.5h-54l-33.5,69.2c0,0,29.7-3.4,38.3,0.8c8.9,4.4,25,30.8,25,30.8l24.2-50V19.5z"/>
+			<path d="M120.4,153.7l-0.6,25l23.8-16.9c0,0-8-7-11.2-8.1C129.4,152.8,120.4,153.7,120.4,153.7z"/>
+			<polyline fill="none" stroke="#231F20" stroke-width="5" points="153.9,19.5 121.6,88.7 120.7,181.2 186.6,120.3 209.1,70.3 "/>
+		  </g>
+		</svg>
+	</g>
+	
+	<g id="svg_eof"/>
+</svg>

+ 21 - 0
main/inc/lib/svg-edit/extensions/helloworld-icon.xml

@@ -0,0 +1,21 @@
+<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="hello_world">
+		<svg width="102" height="102" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+		 <!-- Created with SVG-edit - http://svg-edit.googlecode.com/ -->
+		 <g>
+		  <title>Layer 1</title>
+		  <rect ry="30" rx="30" x="2.5" y="2.5" width="97" height="97" id="svg_3" fill="#008000" stroke="#000000" stroke-width="5"/>
+		  <text x="52.668" y="42.5" id="svg_1" fill="#ffffff" stroke="#000000" stroke-width="0" font-size="24" font-family="Monospace" text-anchor="middle" xml:space="preserve">Hello</text>
+		  <text x="52.668" y="71.5" fill="#ffffff" stroke="#000000" stroke-width="0" font-size="24" font-family="Monospace" text-anchor="middle" xml:space="preserve" id="svg_2">World!</text>
+		 </g>
+		</svg>
+	</g>
+</svg>

+ 115 - 0
main/inc/lib/svg-edit/extensions/markers-icons.xml

@@ -0,0 +1,115 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+    <!-- Created with SVG-edit - http://svg-edit.googlecode.com/ -->
+    <g id="nomarker">
+        <svg viewBox="-60 -60 120 120" xmlns="http://www.w3.org/2000/svg">
+            <path stroke-width="10" stroke="#ff7f00" fill="#ff7f00" d="m-50,0l100,0"/>
+        </svg>
+    </g>
+    <g id="leftarrow">
+        <svg viewBox="-60 -60 120 120" xmlns="http://www.w3.org/2000/svg">
+            <path stroke-width="10" stroke="#ff7f00" fill="#ff7f00" d="m-50,0l100,40l-30,-40l30,-40z"/>
+        </svg>
+    </g>
+    <g id="rightarrow">
+        <svg viewBox="-60 -60 120 120" xmlns="http://www.w3.org/2000/svg">
+            <path stroke-width="10" stroke="#ff7f00" fill="#ff7f00" d="m50,0l-100,40l30,-40l-30,-40z"/>
+        </svg>
+    </g>
+    <g id="leftarrow_o">
+        <svg viewBox="-60 -60 120 120" xmlns="http://www.w3.org/2000/svg">
+            <path stroke-width="10" stroke="#ff7f00" fill="none" d="m-50,0l100,40l-30,-40l30,-40z"/>
+        </svg>
+    </g>
+    <g id="rightarrow_o">
+        <svg viewBox="-60 -60 120 120" xmlns="http://www.w3.org/2000/svg">
+            <path stroke-width="10" stroke="#ff7f00" fill="none" d="m50,0l-100,40l30,-40l-30,-40z"/>
+        </svg>
+    </g>
+    <g id="forwardslash">
+        <svg viewBox="-60 -60 120 120" xmlns="http://www.w3.org/2000/svg">
+            <path stroke-width="10" stroke="#ff7f00" fill="none" d="m-20,50l40,-100"/>
+        </svg>
+    </g>
+    <g id="reverseslash">
+        <svg viewBox="-60 -60 120 120" xmlns="http://www.w3.org/2000/svg">
+            <path stroke-width="10" stroke="#ff7f00" fill="none" d="m-20,-50l40,100"/>
+        </svg>
+    </g>
+    <g id="verticalslash">
+        <svg viewBox="-60 -60 120 120" xmlns="http://www.w3.org/2000/svg">
+            <path stroke-width="10" stroke="#ff7f00" fill="none" d="m0,-50l0,100"/>
+        </svg>
+    </g>
+    <g id="mcircle">
+        <svg viewBox="-60 -60 120 120" xmlns="http://www.w3.org/2000/svg">
+            <circle stroke-width="10" stroke="#ff7f00" fill="#ff7f00" cy="0" cx="0" r="30"/>
+        </svg>
+    </g>
+    <g id="mcircle_o">
+        <svg viewBox="-60 -60 120 120" xmlns="http://www.w3.org/2000/svg">
+            <circle stroke-width="10" stroke="#ff7f00" fill="none" cy="0" cx="0" r="30"/>
+        </svg>
+    </g>
+    <g id="xmark">
+        <svg viewBox="-60 -60 120 120" xmlns="http://www.w3.org/2000/svg">
+            <path stroke-width="10" stroke="#ff7f00" fill="#ff7f00" d="m-30,30l60,-60m0,60l-60,-60"/>
+        </svg>
+    </g>
+    <g id="box">
+        <svg viewBox="-60 -60 120 120" xmlns="http://www.w3.org/2000/svg">
+            <path stroke-width="10" stroke="#ff7f00" fill="#ff7f00" d="m-30,-30l0,60l60,0l0,-60z"/>
+        </svg>
+    </g>
+    <g id="star">
+        <svg viewBox="-60 -60 120 120" xmlns="http://www.w3.org/2000/svg">
+            <path stroke-width="10" stroke="#ff7f00" fill="#ff7f00" d="m-40,-20l80,0l-70,60l30,-80l30,80z"/>
+        </svg>
+    </g>
+    <g id="box_o">
+        <svg viewBox="-60 -60 120 120" xmlns="http://www.w3.org/2000/svg">
+            <path stroke-width="10" stroke="#ff7f00" fill="none" d="m-30,-30l0,60l60,0l0,-60z"/>
+        </svg>
+    </g>
+    <g id="star_o">
+        <svg viewBox="-60 -60 120 120" xmlns="http://www.w3.org/2000/svg">
+            <path stroke-width="10" stroke="#ff7f00" fill="none" d="m-40,-20l80,0l-70,60l30,-80l30,80z"/>
+        </svg>
+    </g>
+     <g id="triangle_o">
+        <svg viewBox="-60 -60 120 120" xmlns="http://www.w3.org/2000/svg">
+            <path stroke-width="10" stroke="#ff7f00" fill="none" d="M-30,30 L0,-30 L30,30 Z"/>
+        </svg>
+    </g>
+     <g id="triangle">
+        <svg viewBox="-60 -60 120 120" xmlns="http://www.w3.org/2000/svg">
+            <path stroke-width="10" stroke="#ff7f00" fill="#ff7f00" d="M-30,30 L0,-30 L30,30 Z"/>
+        </svg>
+    </g>
+   <g id="textmarker">
+        <svg viewBox="-60 -60 120 120" xmlns="http://www.w3.org/2000/svg">
+			<text xml:space="preserve" text-anchor="middle" font-family="serif" font-size="120"  y="40" x="0" stroke-width="0" stroke="#ff7f00" fill="#ff7f00">T</text>	
+        </svg>
+    </g>
+	<g id="mkr_markers_off">
+        <svg viewBox="-60 -60 120 120" xmlns="http://www.w3.org/2000/svg">
+		   <line y2="0" x2="50" y1="0" x1="-50" stroke-width="5" stroke="#ff7f00" fill="none"/>
+       </svg>
+    </g>
+	<g id="mkr_markers_dimension">
+        <svg viewBox="-60 -60 120 120" xmlns="http://www.w3.org/2000/svg">
+ 		   <line y2="0" x2="40" y1="0" x1="20" stroke-width="5" stroke="#ff7f00" fill="none"/>
+		   <line y2="0" x2="-40" y1="0" x1="-20" stroke-width="5" stroke="#ff7f00" fill="none"/>
+		   <text text-anchor="middle" font-family="serif" font-size="80"  y="20" x="0" stroke-width="0" stroke="#ff7f00" fill="#ff7f00">T</text>
+           <path stroke-width="5" stroke="#ff7f00" fill="#ff7f00" d="M-50,0 L-30,-15 L-30,15 Z"/>
+           <path stroke-width="5" stroke="#ff7f00" fill="#ff7f00" d="M50,0 L30,-15 L30,15 Z"/>
+ 		</svg>
+    </g>
+   	<g id="mkr_markers_label">
+        <svg viewBox="-60 -60 120 120" xmlns="http://www.w3.org/2000/svg">
+  		   <line y2="0" x2="40" y1="0" x1="-20" stroke-width="5" stroke="#ff7f00" fill="none"/>
+		   <text text-anchor="middle" font-family="serif" font-size="80"  y="20" x="-40" stroke-width="0" stroke="#ff7f00" fill="#ff7f00">T</text>
+           <path stroke-width="5" stroke="#ff7f00" fill="#ff7f00" d="M50,0 L30,-15 L30,15 Z"/>
+        </svg>
+    </g>
+	<g id="svg_eof"/>
+</svg>

+ 61 - 0
main/inc/lib/svg-edit/images/README.txt

@@ -0,0 +1,61 @@
+filename                        origin
+
+align-bottom.png                http://tango.freedesktop.org/static/cvs/tango-art-libre/22x22/actions/align-vertical-bottom.png
+align-bottom.svg                http://tango.freedesktop.org/static/cvs/tango-art-libre/22x22/actions/align-vertical-bottom.svg
+align-center.png                http://tango.freedesktop.org/static/cvs/tango-art-libre/22x22/actions/align-horizontal-center.png
+align-center.svg                http://tango.freedesktop.org/static/cvs/tango-art-libre/22x22/actions/align-horizontal-center.svg
+align-left.png                  http://tango.freedesktop.org/static/cvs/tango-art-libre/22x22/actions/align-horizontal-left.png
+align-left.svg                  http://tango.freedesktop.org/static/cvs/tango-art-libre/22x22/actions/align-horizontal-left.svg
+align-middle.png                http://tango.freedesktop.org/static/cvs/tango-art-libre/22x22/actions/align-vertical-center.png
+align-middle.svg                http://tango.freedesktop.org/static/cvs/tango-art-libre/22x22/actions/align-vertical-center.svg
+align-right.png                 http://tango.freedesktop.org/static/cvs/tango-art-libre/22x22/actions/align-horizontal-right.png
+align-right.svg                 http://tango.freedesktop.org/static/cvs/tango-art-libre/22x22/actions/align-horizontal-right.svg
+align-top.png                   http://tango.freedesktop.org/static/cvs/tango-art-libre/22x22/actions/align-vertical-top.png
+align-top.svg                   http://tango.freedesktop.org/static/cvs/tango-art-libre/22x22/actions/align-vertical-top.svg
+bold.png
+cancel.png
+circle.png
+clear.png
+clone.png
+copy.png
+cut.png
+delete.png
+document-properties.png
+dropdown.gif
+ellipse.png
+eye.png
+flyouth.png
+flyup.gif
+freehand-circle.png
+freehand-square.png
+go-down.png
+go-up.png
+image.png
+italic.png
+line.png
+logo.png
+logo.svg
+move_bottom.png
+move_top.png
+none.png
+open.png
+paste.png
+path.png
+polygon.png                     http://tango.freedesktop.org/static/cvs/tango-art-libre/22x22/tools/draw-polygon.png
+polygon.svg                     http://tango.freedesktop.org/static/cvs/tango-art-libre/22x22/tools/draw-polygon.svg
+rect.png
+redo.png
+rotate.png
+save.png
+select.png
+sep.png
+shape_group.png
+shape_ungroup.png
+source.png
+square.png
+text.png                        http://tango.freedesktop.org/static/cvs/tango-art-libre/22x22/tools/draw-text.png
+text.svg                        http://tango.freedesktop.org/static/cvs/tango-art-libre/22x22/tools/draw-text.svg
+undo.png
+view-refresh.png
+wave.png
+zoom.png                        http://tango.freedesktop.org/static/cvs/tango-art-libre/22x22/tools/page-magnifier.png

BIN
main/inc/lib/svg-edit/images/align-bottom.png


+ 277 - 0
main/inc/lib/svg-edit/images/align-bottom.svg

@@ -0,0 +1,277 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="22"
+   height="22"
+   id="svg5741"
+   sodipodi:version="0.32"
+   inkscape:version="0.44+devel"
+   version="1.0"
+   sodipodi:docbase="/home/andreas/project/inkscape/22x22/actions"
+   sodipodi:docname="align-bottom-vertical.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   inkscape:export-filename="/home/andreas/project/inkscape/22x22/actions/align-bottom-vertical.png"
+   inkscape:export-xdpi="90"
+   inkscape:export-ydpi="90"
+   sodipodi:modified="true">
+  <defs
+     id="defs5743">
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2968"
+       id="linearGradient6938"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-1,0,0,-1,395.9999,981)"
+       x1="187.60938"
+       y1="489.35938"
+       x2="186.93732"
+       y2="489.35938" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2974"
+       id="linearGradient6936"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-1,0,0,-1,395.9999,981)"
+       x1="187.81554"
+       y1="489.54688"
+       x2="187.1716"
+       y2="489.54688" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2986"
+       id="linearGradient6934"
+       gradientUnits="userSpaceOnUse"
+       x1="187.60938"
+       y1="489.35938"
+       x2="186.93732"
+       y2="489.35938" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2980"
+       id="linearGradient6932"
+       gradientUnits="userSpaceOnUse"
+       x1="187.81554"
+       y1="489.54688"
+       x2="187.1716"
+       y2="489.54688" />
+    <linearGradient
+       id="linearGradient2968"
+       inkscape:collect="always">
+      <stop
+         id="stop2970"
+         offset="0"
+         style="stop-color:#ce5c00;stop-opacity:1" />
+      <stop
+         id="stop2972"
+         offset="1"
+         style="stop-color:#ce5c00;stop-opacity:0" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2968"
+       id="linearGradient6930"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-1,0,0,-1,395.9999,981)"
+       x1="187.60938"
+       y1="489.35938"
+       x2="186.93732"
+       y2="489.35938" />
+    <linearGradient
+       id="linearGradient2974"
+       inkscape:collect="always">
+      <stop
+         id="stop2976"
+         offset="0"
+         style="stop-color:#fcaf3e;stop-opacity:1" />
+      <stop
+         id="stop2978"
+         offset="1"
+         style="stop-color:#fcaf3e;stop-opacity:0" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2974"
+       id="linearGradient6928"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-1,0,0,-1,395.9999,981)"
+       x1="187.81554"
+       y1="489.54688"
+       x2="187.1716"
+       y2="489.54688" />
+    <linearGradient
+       id="linearGradient2986"
+       inkscape:collect="always">
+      <stop
+         id="stop2988"
+         offset="0"
+         style="stop-color:#ce5c00;stop-opacity:1" />
+      <stop
+         id="stop2990"
+         offset="1"
+         style="stop-color:#ce5c00;stop-opacity:0" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2986"
+       id="linearGradient6926"
+       gradientUnits="userSpaceOnUse"
+       x1="187.60938"
+       y1="489.35938"
+       x2="186.93732"
+       y2="489.35938" />
+    <linearGradient
+       id="linearGradient2980"
+       inkscape:collect="always">
+      <stop
+         id="stop2982"
+         offset="0"
+         style="stop-color:#fcaf3e;stop-opacity:1" />
+      <stop
+         id="stop2984"
+         offset="1"
+         style="stop-color:#fcaf3e;stop-opacity:0" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2980"
+       id="linearGradient6924"
+       gradientUnits="userSpaceOnUse"
+       x1="187.81554"
+       y1="489.54688"
+       x2="187.1716"
+       y2="489.54688" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="22.197802"
+     inkscape:cx="8"
+     inkscape:cy="9.8019802"
+     inkscape:current-layer="g6828"
+     showgrid="false"
+     inkscape:grid-bbox="true"
+     inkscape:document-units="px"
+     width="22px"
+     height="22px"
+     inkscape:window-width="1078"
+     inkscape:window-height="786"
+     inkscape:window-x="243"
+     inkscape:window-y="71" />
+  <metadata
+     id="metadata5746">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer">
+    <g
+       style="display:inline"
+       id="g6828"
+       transform="translate(30.00011,90.000366)"
+       inkscape:export-filename="/home/lapo/Desktop/align-distribute.tar.gz_FILES/align-stuff.png"
+       inkscape:export-xdpi="90"
+       inkscape:export-ydpi="90">
+      <g
+         style="display:inline"
+         id="g6838"
+         transform="translate(-30.00009,-1.0002798)"
+         inkscape:export-filename="/home/lapo/Desktop/align-distribute.tar.gz_FILES/align-stuff.png"
+         inkscape:export-xdpi="90"
+         inkscape:export-ydpi="90">
+        <rect
+           style="fill:#d3d7cf;fill-opacity:1;stroke:#888a85;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:3;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+           id="rect3052"
+           width="12"
+           height="7"
+           x="69.500122"
+           y="12.5"
+           transform="matrix(0,-1,1,0,0,0)"
+           inkscape:export-filename="/home/lapo/Desktop/align-distribute.tar.gz_FILES/align-stuff.png"
+           inkscape:export-xdpi="90"
+           inkscape:export-ydpi="90" />
+        <rect
+           style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+           id="rect3054"
+           width="10"
+           height="5.0000305"
+           x="70.500122"
+           y="13.5"
+           transform="matrix(0,-1,1,0,0,0)"
+           rx="0"
+           ry="0"
+           inkscape:export-filename="/home/lapo/Desktop/align-distribute.tar.gz_FILES/align-stuff.png"
+           inkscape:export-xdpi="90"
+           inkscape:export-ydpi="90" />
+        <g
+           id="g3056"
+           transform="translate(-127,-559)"
+           inkscape:export-filename="/home/lapo/Desktop/align-distribute.tar.gz_FILES/align-stuff.png"
+           inkscape:export-xdpi="90"
+           inkscape:export-ydpi="90">
+          <rect
+             transform="matrix(0,-1,1,0,0,0)"
+             y="129.49626"
+             x="-489.49979"
+             height="7.0035982"
+             width="17.999748"
+             id="rect3058"
+             style="color:#000000;fill:#d3d7cf;fill-opacity:1;fill-rule:evenodd;stroke:#888a85;stroke-width:1.00024867;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline" />
+          <rect
+             transform="matrix(0,-1,1,0,0,0)"
+             y="130.50006"
+             x="-488.50009"
+             height="4.9998937"
+             width="15.999757"
+             id="rect3060"
+             style="color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.00024891;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:2;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+             rx="0"
+             ry="0" />
+        </g>
+        <g
+           id="g3294"
+           transform="translate(-187,-560)"
+           inkscape:export-filename="/home/lapo/Desktop/align-distribute.tar.gz_FILES/align-stuff.png"
+           inkscape:export-xdpi="90"
+           inkscape:export-ydpi="90">
+          <rect
+             y="489.5"
+             x="196.49989"
+             height="1.9999999"
+             width="3.0000916"
+             id="rect3296"
+             style="fill:#fcaf3e;fill-opacity:1;stroke:#ce5c00;stroke-width:0.99999976;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+          <path
+             style="fill:url(#linearGradient6932);fill-opacity:1;stroke:url(#linearGradient6934);stroke-width:0.99999976;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:0;stroke-dashoffset:0;stroke-opacity:1"
+             d="M 197.49998,491.5 L 186.49989,491.5 L 186.49989,489.5 L 197.49998,489.5"
+             id="path3298"
+             sodipodi:nodetypes="cccc" />
+          <path
+             style="fill:url(#linearGradient6936);fill-opacity:1;stroke:url(#linearGradient6938);stroke-width:0.99999976;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:0;stroke-dashoffset:0;stroke-opacity:1"
+             d="M 198.49989,489.5 L 209.49998,489.5 L 209.49998,491.5 L 198.49989,491.5"
+             id="path3300"
+             sodipodi:nodetypes="cccc" />
+        </g>
+      </g>
+    </g>
+  </g>
+</svg>

BIN
main/inc/lib/svg-edit/images/align-center.png


+ 252 - 0
main/inc/lib/svg-edit/images/align-center.svg

@@ -0,0 +1,252 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="22"
+   height="22"
+   id="svg10958"
+   sodipodi:version="0.32"
+   inkscape:version="0.44+devel"
+   version="1.0"
+   sodipodi:docbase="/home/andreas/project/inkscape/22x22/actions"
+   sodipodi:docname="align-horisontal-center.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   inkscape:export-filename="/home/andreas/project/inkscape/22x22/actions/align-horisontal-center.png"
+   inkscape:export-xdpi="90"
+   inkscape:export-ydpi="90"
+   sodipodi:modified="true">
+  <defs
+     id="defs10960">
+    <linearGradient
+       id="linearGradient2968"
+       inkscape:collect="always">
+      <stop
+         id="stop2970"
+         offset="0"
+         style="stop-color:#ce5c00;stop-opacity:1" />
+      <stop
+         id="stop2972"
+         offset="1"
+         style="stop-color:#ce5c00;stop-opacity:0" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2968"
+       id="linearGradient4708"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-395.9999,-981)"
+       x1="187.60938"
+       y1="489.35938"
+       x2="186.93732"
+       y2="489.35938" />
+    <linearGradient
+       id="linearGradient2974"
+       inkscape:collect="always">
+      <stop
+         id="stop2976"
+         offset="0"
+         style="stop-color:#fcaf3e;stop-opacity:1" />
+      <stop
+         id="stop2978"
+         offset="1"
+         style="stop-color:#fcaf3e;stop-opacity:0" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2974"
+       id="linearGradient4706"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-395.9999,-981)"
+       x1="187.81554"
+       y1="489.54688"
+       x2="187.1716"
+       y2="489.54688" />
+    <linearGradient
+       id="linearGradient2986"
+       inkscape:collect="always">
+      <stop
+         id="stop2988"
+         offset="0"
+         style="stop-color:#ce5c00;stop-opacity:1" />
+      <stop
+         id="stop2990"
+         offset="1"
+         style="stop-color:#ce5c00;stop-opacity:0" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2986"
+       id="linearGradient4704"
+       gradientUnits="userSpaceOnUse"
+       x1="187.60938"
+       y1="489.35938"
+       x2="186.93732"
+       y2="489.35938" />
+    <linearGradient
+       id="linearGradient2980"
+       inkscape:collect="always">
+      <stop
+         id="stop2982"
+         offset="0"
+         style="stop-color:#fcaf3e;stop-opacity:1" />
+      <stop
+         id="stop2984"
+         offset="1"
+         style="stop-color:#fcaf3e;stop-opacity:0" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2980"
+       id="linearGradient4702"
+       gradientUnits="userSpaceOnUse"
+       x1="187.81554"
+       y1="489.54688"
+       x2="187.1716"
+       y2="489.54688" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="11.197802"
+     inkscape:cx="16"
+     inkscape:cy="11.460711"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:grid-bbox="true"
+     inkscape:document-units="px"
+     width="22px"
+     height="22px"
+     inkscape:window-width="797"
+     inkscape:window-height="628"
+     inkscape:window-x="0"
+     inkscape:window-y="47" />
+  <metadata
+     id="metadata10963">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer">
+    <g
+       style="display:inline"
+       id="g4044"
+       transform="matrix(0,-1,1,0,-59.999911,-168.00002)"
+       inkscape:export-filename="/home/lapo/Desktop/align-distribute.tar.gz_FILES/align-stuff.png"
+       inkscape:export-xdpi="90"
+       inkscape:export-ydpi="90">
+      <rect
+         style="fill:#d3d7cf;fill-opacity:1;stroke:#888a85;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:3;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+         id="rect3851"
+         width="12"
+         height="7"
+         x="-76.499878"
+         y="-177.5"
+         transform="matrix(0,-1,1,0,0,0)"
+         inkscape:export-filename="/home/lapo/Desktop/align-distribute.tar.gz_FILES/align-stuff.png"
+         inkscape:export-xdpi="90"
+         inkscape:export-ydpi="90" />
+      <g
+         transform="translate(-317,-410)"
+         id="g3853"
+         inkscape:export-filename="/home/lapo/Desktop/align-distribute.tar.gz_FILES/align-stuff.png"
+         inkscape:export-xdpi="90"
+         inkscape:export-ydpi="90"
+         style="display:inline">
+        <rect
+           transform="matrix(0,-1,1,0,0,0)"
+           y="129.49626"
+           x="-489.49979"
+           height="7.0035982"
+           width="17.999748"
+           id="rect3855"
+           style="color:#000000;fill:#d3d7cf;fill-opacity:1;fill-rule:evenodd;stroke:#888a85;stroke-width:1.00024867;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline" />
+        <rect
+           transform="matrix(0,-1,1,0,0,0)"
+           y="130.50006"
+           x="-488.50009"
+           height="4.9998937"
+           width="15.999757"
+           id="rect3857"
+           style="color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.00024891;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:2;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+           rx="0"
+           ry="0" />
+      </g>
+      <rect
+         style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+         id="rect3859"
+         width="10"
+         height="5.0000305"
+         x="-75.499878"
+         y="-176.5"
+         transform="matrix(0,-1,1,0,0,0)"
+         rx="0"
+         ry="0"
+         inkscape:export-filename="/home/lapo/Desktop/align-distribute.tar.gz_FILES/align-stuff.png"
+         inkscape:export-xdpi="90"
+         inkscape:export-ydpi="90" />
+      <g
+         id="g3861"
+         transform="translate(-377,-420)"
+         inkscape:export-filename="/home/lapo/Desktop/align-distribute.tar.gz_FILES/align-stuff.png"
+         inkscape:export-xdpi="90"
+         inkscape:export-ydpi="90"
+         style="display:inline">
+        <rect
+           y="489.5"
+           x="186.49989"
+           height="1.9999999"
+           width="3.0000916"
+           id="rect3863"
+           style="fill:url(#linearGradient4702);fill-opacity:1;stroke:url(#linearGradient4704);stroke-width:0.99999976;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+        <rect
+           y="489.5"
+           x="191.49989"
+           height="1.9999999"
+           width="3.0000916"
+           id="rect3865"
+           style="fill:#fcaf3e;fill-opacity:1;stroke:#ce5c00;stroke-width:0.99999976;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+        <rect
+           y="489.5"
+           x="196.49989"
+           height="1.9999999"
+           width="3.0000916"
+           id="rect3867"
+           style="fill:#fcaf3e;fill-opacity:1;stroke:#ce5c00;stroke-width:0.99999976;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+        <rect
+           y="489.5"
+           x="201.49989"
+           height="1.9999999"
+           width="3.0000916"
+           id="rect3869"
+           style="fill:#fcaf3e;fill-opacity:1;stroke:#ce5c00;stroke-width:0.99999976;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+        <rect
+           transform="scale(-1,-1)"
+           y="-491.5"
+           x="-209.49998"
+           height="1.9999999"
+           width="3.0000916"
+           id="rect3871"
+           style="fill:url(#linearGradient4706);fill-opacity:1;stroke:url(#linearGradient4708);stroke-width:0.99999976;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+      </g>
+    </g>
+  </g>
+</svg>

BIN
main/inc/lib/svg-edit/images/align-left.png


+ 235 - 0
main/inc/lib/svg-edit/images/align-left.svg

@@ -0,0 +1,235 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="22"
+   height="22"
+   id="svg11272"
+   sodipodi:version="0.32"
+   inkscape:version="0.44+devel"
+   version="1.0"
+   sodipodi:docbase="/home/andreas/project/inkscape/22x22/actions"
+   sodipodi:docname="align-horisontal-left.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   inkscape:export-filename="/home/andreas/project/inkscape/22x22/actions/align-horisontal-left.png"
+   inkscape:export-xdpi="90"
+   inkscape:export-ydpi="90"
+   sodipodi:modified="true">
+  <defs
+     id="defs11274">
+    <linearGradient
+       id="linearGradient2968"
+       inkscape:collect="always">
+      <stop
+         id="stop2970"
+         offset="0"
+         style="stop-color:#ce5c00;stop-opacity:1" />
+      <stop
+         id="stop2972"
+         offset="1"
+         style="stop-color:#ce5c00;stop-opacity:0" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2968"
+       id="linearGradient4716"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-1,0,0,-1,395.9999,981)"
+       x1="187.60938"
+       y1="489.35938"
+       x2="186.93732"
+       y2="489.35938" />
+    <linearGradient
+       id="linearGradient2974"
+       inkscape:collect="always">
+      <stop
+         id="stop2976"
+         offset="0"
+         style="stop-color:#fcaf3e;stop-opacity:1" />
+      <stop
+         id="stop2978"
+         offset="1"
+         style="stop-color:#fcaf3e;stop-opacity:0" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2974"
+       id="linearGradient4714"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-1,0,0,-1,395.9999,981)"
+       x1="187.81554"
+       y1="489.54688"
+       x2="187.1716"
+       y2="489.54688" />
+    <linearGradient
+       id="linearGradient2986"
+       inkscape:collect="always">
+      <stop
+         id="stop2988"
+         offset="0"
+         style="stop-color:#ce5c00;stop-opacity:1" />
+      <stop
+         id="stop2990"
+         offset="1"
+         style="stop-color:#ce5c00;stop-opacity:0" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2986"
+       id="linearGradient4712"
+       gradientUnits="userSpaceOnUse"
+       x1="187.60938"
+       y1="489.35938"
+       x2="186.93732"
+       y2="489.35938" />
+    <linearGradient
+       id="linearGradient2980"
+       inkscape:collect="always">
+      <stop
+         id="stop2982"
+         offset="0"
+         style="stop-color:#fcaf3e;stop-opacity:1" />
+      <stop
+         id="stop2984"
+         offset="1"
+         style="stop-color:#fcaf3e;stop-opacity:0" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2980"
+       id="linearGradient4710"
+       gradientUnits="userSpaceOnUse"
+       x1="187.81554"
+       y1="489.54688"
+       x2="187.1716"
+       y2="489.54688" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="11.197802"
+     inkscape:cx="16"
+     inkscape:cy="14.269093"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:grid-bbox="true"
+     inkscape:document-units="px"
+     width="22px"
+     height="22px"
+     inkscape:window-width="797"
+     inkscape:window-height="628"
+     inkscape:window-x="0"
+     inkscape:window-y="47" />
+  <metadata
+     id="metadata11277">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer">
+    <g
+       style="display:inline"
+       id="g4065"
+       transform="matrix(0,-1,1,0,8.9287758e-5,51.99998)"
+       inkscape:export-filename="/home/lapo/Desktop/align-distribute.tar.gz_FILES/align-stuff.png"
+       inkscape:export-xdpi="90"
+       inkscape:export-ydpi="90">
+      <g
+         id="g3883"
+         transform="translate(-127,-473)"
+         style="fill:#d3d7cf;stroke:#888a85;display:inline"
+         inkscape:export-filename="/home/lapo/Desktop/align-distribute.tar.gz_FILES/align-stuff.png"
+         inkscape:export-xdpi="90"
+         inkscape:export-ydpi="90">
+        <rect
+           transform="matrix(0,1,1,0,0,0)"
+           y="169.5"
+           x="475.50012"
+           height="7"
+           width="12"
+           id="rect3885"
+           style="fill:#d3d7cf;fill-opacity:1;stroke:#888a85;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:3;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+        <rect
+           ry="0"
+           rx="0"
+           transform="matrix(0,1,1,0,0,0)"
+           y="170.5"
+           x="476.50012"
+           height="5.0000305"
+           width="10"
+           id="rect3887"
+           style="opacity:1;fill:#d3d7cf;fill-opacity:1;stroke:#ffffff;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+      </g>
+      <g
+         id="g3889"
+         transform="translate(-97,-469)"
+         inkscape:export-filename="/home/lapo/Desktop/align-distribute.tar.gz_FILES/align-stuff.png"
+         inkscape:export-xdpi="90"
+         inkscape:export-ydpi="90"
+         style="display:inline">
+        <rect
+           transform="matrix(0,-1,1,0,0,0)"
+           y="129.49626"
+           x="-489.49979"
+           height="7.0035982"
+           width="17.999748"
+           id="rect3891"
+           style="color:#000000;fill:#d3d7cf;fill-opacity:1;fill-rule:evenodd;stroke:#888a85;stroke-width:1.00024867;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline" />
+        <rect
+           transform="matrix(0,-1,1,0,0,0)"
+           y="130.50006"
+           x="-488.50009"
+           height="4.9998937"
+           width="15.999757"
+           id="rect3893"
+           style="color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.00024891;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:2;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+           rx="0"
+           ry="0" />
+      </g>
+      <g
+         id="g3903"
+         transform="translate(-157,-488)"
+         inkscape:export-filename="/home/lapo/Desktop/align-distribute.tar.gz_FILES/align-stuff.png"
+         inkscape:export-xdpi="90"
+         inkscape:export-ydpi="90"
+         style="display:inline">
+        <rect
+           y="489.5"
+           x="196.49989"
+           height="1.9999999"
+           width="3.0000916"
+           id="rect3905"
+           style="fill:#fcaf3e;fill-opacity:1;stroke:#ce5c00;stroke-width:0.99999976;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+        <path
+           style="fill:url(#linearGradient4710);fill-opacity:1;stroke:url(#linearGradient4712);stroke-width:0.99999976;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:0;stroke-dashoffset:0;stroke-opacity:1"
+           d="M 197.49998,491.5 L 186.49989,491.5 L 186.49989,489.5 L 197.49998,489.5"
+           id="path3907"
+           sodipodi:nodetypes="cccc" />
+        <path
+           style="fill:url(#linearGradient4714);fill-opacity:1;stroke:url(#linearGradient4716);stroke-width:0.99999976;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:0;stroke-dashoffset:0;stroke-opacity:1"
+           d="M 198.49989,489.5 L 209.49998,489.5 L 209.49998,491.5 L 198.49989,491.5"
+           id="path3909"
+           sodipodi:nodetypes="cccc" />
+      </g>
+    </g>
+  </g>
+</svg>

BIN
main/inc/lib/svg-edit/images/align-middle.png


+ 250 - 0
main/inc/lib/svg-edit/images/align-middle.svg

@@ -0,0 +1,250 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="22"
+   height="22"
+   id="svg10625"
+   sodipodi:version="0.32"
+   inkscape:version="0.44+devel"
+   version="1.0"
+   sodipodi:docbase="/home/andreas/project/inkscape/22x22/actions"
+   sodipodi:docname="align-vertical-center.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   inkscape:export-filename="/home/andreas/project/inkscape/22x22/actions/align-vertical-center.png"
+   inkscape:export-xdpi="90"
+   inkscape:export-ydpi="90"
+   sodipodi:modified="true">
+  <defs
+     id="defs10627">
+    <linearGradient
+       id="linearGradient2968"
+       inkscape:collect="always">
+      <stop
+         id="stop2970"
+         offset="0"
+         style="stop-color:#ce5c00;stop-opacity:1" />
+      <stop
+         id="stop2972"
+         offset="1"
+         style="stop-color:#ce5c00;stop-opacity:0" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2968"
+       id="linearGradient6962"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-395.9999,-981)"
+       x1="187.60938"
+       y1="489.35938"
+       x2="186.93732"
+       y2="489.35938" />
+    <linearGradient
+       id="linearGradient2974"
+       inkscape:collect="always">
+      <stop
+         id="stop2976"
+         offset="0"
+         style="stop-color:#fcaf3e;stop-opacity:1" />
+      <stop
+         id="stop2978"
+         offset="1"
+         style="stop-color:#fcaf3e;stop-opacity:0" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2974"
+       id="linearGradient6960"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-395.9999,-981)"
+       x1="187.81554"
+       y1="489.54688"
+       x2="187.1716"
+       y2="489.54688" />
+    <linearGradient
+       id="linearGradient2986"
+       inkscape:collect="always">
+      <stop
+         id="stop2988"
+         offset="0"
+         style="stop-color:#ce5c00;stop-opacity:1" />
+      <stop
+         id="stop2990"
+         offset="1"
+         style="stop-color:#ce5c00;stop-opacity:0" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2986"
+       id="linearGradient6958"
+       gradientUnits="userSpaceOnUse"
+       x1="187.60938"
+       y1="489.35938"
+       x2="186.93732"
+       y2="489.35938" />
+    <linearGradient
+       id="linearGradient2980"
+       inkscape:collect="always">
+      <stop
+         id="stop2982"
+         offset="0"
+         style="stop-color:#fcaf3e;stop-opacity:1" />
+      <stop
+         id="stop2984"
+         offset="1"
+         style="stop-color:#fcaf3e;stop-opacity:0" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2980"
+       id="linearGradient6956"
+       gradientUnits="userSpaceOnUse"
+       x1="187.81554"
+       y1="489.54688"
+       x2="187.1716"
+       y2="489.54688" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="11.197802"
+     inkscape:cx="16"
+     inkscape:cy="16"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:grid-bbox="true"
+     inkscape:document-units="px"
+     width="22px"
+     height="22px"
+     inkscape:window-width="797"
+     inkscape:window-height="628"
+     inkscape:window-x="0"
+     inkscape:window-y="47" />
+  <metadata
+     id="metadata10630">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer">
+    <g
+       style="display:inline"
+       id="g6849"
+       transform="translate(-29.999893,91.000089)"
+       inkscape:export-filename="/home/lapo/Desktop/align-distribute.tar.gz_FILES/align-stuff.png"
+       inkscape:export-xdpi="90"
+       inkscape:export-ydpi="90">
+      <rect
+         style="fill:#d3d7cf;fill-opacity:1;stroke:#888a85;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:3;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+         id="rect1933"
+         width="12"
+         height="7"
+         x="73.500122"
+         y="42.5"
+         transform="matrix(0,-1,1,0,0,0)"
+         inkscape:export-filename="/home/lapo/Desktop/align-distribute.tar.gz_FILES/align-stuff.png"
+         inkscape:export-xdpi="90"
+         inkscape:export-ydpi="90" />
+      <g
+         transform="translate(-97,-560)"
+         id="g2063"
+         inkscape:export-filename="/home/lapo/Desktop/align-distribute.tar.gz_FILES/align-stuff.png"
+         inkscape:export-xdpi="90"
+         inkscape:export-ydpi="90">
+        <rect
+           transform="matrix(0,-1,1,0,0,0)"
+           y="129.49626"
+           x="-489.49979"
+           height="7.0035982"
+           width="17.999748"
+           id="rect1935"
+           style="color:#000000;fill:#d3d7cf;fill-opacity:1;fill-rule:evenodd;stroke:#888a85;stroke-width:1.00024867;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline" />
+        <rect
+           transform="matrix(0,-1,1,0,0,0)"
+           y="130.50006"
+           x="-488.50009"
+           height="4.9998937"
+           width="15.999757"
+           id="rect1937"
+           style="color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.00024891;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:2;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+           rx="0"
+           ry="0" />
+      </g>
+      <rect
+         style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+         id="rect1939"
+         width="10"
+         height="5.0000305"
+         x="74.500122"
+         y="43.5"
+         transform="matrix(0,-1,1,0,0,0)"
+         rx="0"
+         ry="0"
+         inkscape:export-filename="/home/lapo/Desktop/align-distribute.tar.gz_FILES/align-stuff.png"
+         inkscape:export-xdpi="90"
+         inkscape:export-ydpi="90" />
+      <g
+         id="g2992"
+         transform="translate(-157,-570)"
+         inkscape:export-filename="/home/lapo/Desktop/align-distribute.tar.gz_FILES/align-stuff.png"
+         inkscape:export-xdpi="90"
+         inkscape:export-ydpi="90">
+        <rect
+           y="489.5"
+           x="186.49989"
+           height="1.9999999"
+           width="3.0000916"
+           id="rect2994"
+           style="fill:url(#linearGradient6956);fill-opacity:1;stroke:url(#linearGradient6958);stroke-width:0.99999976;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+        <rect
+           y="489.5"
+           x="191.49989"
+           height="1.9999999"
+           width="3.0000916"
+           id="rect2996"
+           style="fill:#fcaf3e;fill-opacity:1;stroke:#ce5c00;stroke-width:0.99999976;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+        <rect
+           y="489.5"
+           x="196.49989"
+           height="1.9999999"
+           width="3.0000916"
+           id="rect2998"
+           style="fill:#fcaf3e;fill-opacity:1;stroke:#ce5c00;stroke-width:0.99999976;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+        <rect
+           y="489.5"
+           x="201.49989"
+           height="1.9999999"
+           width="3.0000916"
+           id="rect3000"
+           style="fill:#fcaf3e;fill-opacity:1;stroke:#ce5c00;stroke-width:0.99999976;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+        <rect
+           transform="scale(-1,-1)"
+           y="-491.5"
+           x="-209.49998"
+           height="1.9999999"
+           width="3.0000916"
+           id="rect3002"
+           style="fill:url(#linearGradient6960);fill-opacity:1;stroke:url(#linearGradient6962);stroke-width:0.99999976;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+      </g>
+    </g>
+  </g>
+</svg>

BIN
main/inc/lib/svg-edit/images/align-right.png


+ 233 - 0
main/inc/lib/svg-edit/images/align-right.svg

@@ -0,0 +1,233 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="22"
+   height="22"
+   id="svg11187"
+   sodipodi:version="0.32"
+   inkscape:version="0.44+devel"
+   version="1.0"
+   sodipodi:docbase="/home/andreas/project/inkscape/22x22/actions"
+   sodipodi:docname="align-horisontal-right.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   sodipodi:modified="TRUE"
+   inkscape:export-filename="/home/andreas/project/inkscape/22x22/actions/align-horisontal-right.png"
+   inkscape:export-xdpi="90"
+   inkscape:export-ydpi="90">
+  <defs
+     id="defs11189">
+    <linearGradient
+       id="linearGradient2968"
+       inkscape:collect="always">
+      <stop
+         id="stop2970"
+         offset="0"
+         style="stop-color:#ce5c00;stop-opacity:1" />
+      <stop
+         id="stop2972"
+         offset="1"
+         style="stop-color:#ce5c00;stop-opacity:0" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2968"
+       id="linearGradient4732"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-1,0,0,-1,395.9999,981)"
+       x1="187.60938"
+       y1="489.35938"
+       x2="186.93732"
+       y2="489.35938" />
+    <linearGradient
+       id="linearGradient2974"
+       inkscape:collect="always">
+      <stop
+         id="stop2976"
+         offset="0"
+         style="stop-color:#fcaf3e;stop-opacity:1" />
+      <stop
+         id="stop2978"
+         offset="1"
+         style="stop-color:#fcaf3e;stop-opacity:0" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2974"
+       id="linearGradient4730"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-1,0,0,-1,395.9999,981)"
+       x1="187.81554"
+       y1="489.54688"
+       x2="187.1716"
+       y2="489.54688" />
+    <linearGradient
+       id="linearGradient2986"
+       inkscape:collect="always">
+      <stop
+         id="stop2988"
+         offset="0"
+         style="stop-color:#ce5c00;stop-opacity:1" />
+      <stop
+         id="stop2990"
+         offset="1"
+         style="stop-color:#ce5c00;stop-opacity:0" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2986"
+       id="linearGradient4728"
+       gradientUnits="userSpaceOnUse"
+       x1="187.60938"
+       y1="489.35938"
+       x2="186.93732"
+       y2="489.35938" />
+    <linearGradient
+       id="linearGradient2980"
+       inkscape:collect="always">
+      <stop
+         id="stop2982"
+         offset="0"
+         style="stop-color:#fcaf3e;stop-opacity:1" />
+      <stop
+         id="stop2984"
+         offset="1"
+         style="stop-color:#fcaf3e;stop-opacity:0" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2980"
+       id="linearGradient4726"
+       gradientUnits="userSpaceOnUse"
+       x1="187.81554"
+       y1="489.54688"
+       x2="187.1716"
+       y2="489.54688" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="11.197802"
+     inkscape:cx="16"
+     inkscape:cy="16"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:grid-bbox="true"
+     inkscape:document-units="px"
+     width="22px"
+     height="22px"
+     inkscape:window-width="797"
+     inkscape:window-height="628"
+     inkscape:window-x="0"
+     inkscape:window-y="47" />
+  <metadata
+     id="metadata11192">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer">
+    <g
+       style="display:inline"
+       id="g4025"
+       transform="matrix(0,-1,1,0,-60.999914,-198.00011)"
+       inkscape:export-filename="/home/lapo/Desktop/align-distribute.tar.gz_FILES/align-stuff.png"
+       inkscape:export-xdpi="90"
+       inkscape:export-ydpi="90">
+      <rect
+         style="fill:#d3d7cf;fill-opacity:1;stroke:#888a85;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:3;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+         id="rect3873"
+         width="12"
+         height="7"
+         x="-80.499878"
+         y="-207.5"
+         transform="matrix(0,-1,1,0,0,0)"
+         inkscape:export-filename="/home/lapo/Desktop/align-distribute.tar.gz_FILES/align-stuff.png"
+         inkscape:export-xdpi="90"
+         inkscape:export-ydpi="90" />
+      <rect
+         style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+         id="rect3875"
+         width="10"
+         height="5.0000305"
+         x="-79.499878"
+         y="-206.5"
+         transform="matrix(0,-1,1,0,0,0)"
+         rx="0"
+         ry="0"
+         inkscape:export-filename="/home/lapo/Desktop/align-distribute.tar.gz_FILES/align-stuff.png"
+         inkscape:export-xdpi="90"
+         inkscape:export-ydpi="90" />
+      <g
+         id="g3877"
+         transform="translate(-347,-409)"
+         inkscape:export-filename="/home/lapo/Desktop/align-distribute.tar.gz_FILES/align-stuff.png"
+         inkscape:export-xdpi="90"
+         inkscape:export-ydpi="90"
+         style="display:inline">
+        <rect
+           transform="matrix(0,-1,1,0,0,0)"
+           y="129.49626"
+           x="-489.49979"
+           height="7.0035982"
+           width="17.999748"
+           id="rect3879"
+           style="color:#000000;fill:#d3d7cf;fill-opacity:1;fill-rule:evenodd;stroke:#888a85;stroke-width:1.00024867;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline" />
+        <rect
+           transform="matrix(0,-1,1,0,0,0)"
+           y="130.50006"
+           x="-488.50009"
+           height="4.9998937"
+           width="15.999757"
+           id="rect3881"
+           style="color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.00024891;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:2;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+           rx="0"
+           ry="0" />
+      </g>
+      <g
+         id="g3919"
+         transform="translate(-407,-410)"
+         inkscape:export-filename="/home/lapo/Desktop/align-distribute.tar.gz_FILES/align-stuff.png"
+         inkscape:export-xdpi="90"
+         inkscape:export-ydpi="90"
+         style="display:inline">
+        <rect
+           y="489.5"
+           x="196.49989"
+           height="1.9999999"
+           width="3.0000916"
+           id="rect3921"
+           style="fill:#fcaf3e;fill-opacity:1;stroke:#ce5c00;stroke-width:0.99999976;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+        <path
+           style="fill:url(#linearGradient4726);fill-opacity:1;stroke:url(#linearGradient4728);stroke-width:0.99999976;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:0;stroke-dashoffset:0;stroke-opacity:1"
+           d="M 197.49998,491.5 L 186.49989,491.5 L 186.49989,489.5 L 197.49998,489.5"
+           id="path3923"
+           sodipodi:nodetypes="cccc" />
+        <path
+           style="fill:url(#linearGradient4730);fill-opacity:1;stroke:url(#linearGradient4732);stroke-width:0.99999976;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:0;stroke-dashoffset:0;stroke-opacity:1"
+           d="M 198.49989,489.5 L 209.49998,489.5 L 209.49998,491.5 L 198.49989,491.5"
+           id="path3925"
+           sodipodi:nodetypes="cccc" />
+      </g>
+    </g>
+  </g>
+</svg>

BIN
main/inc/lib/svg-edit/images/align-top.png


+ 233 - 0
main/inc/lib/svg-edit/images/align-top.svg

@@ -0,0 +1,233 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="22"
+   height="22"
+   id="svg10699"
+   sodipodi:version="0.32"
+   inkscape:version="0.44+devel"
+   version="1.0"
+   sodipodi:docbase="/home/andreas/project/inkscape/22x22/actions"
+   sodipodi:docname="align-vertical-bottom.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   inkscape:export-filename="/home/andreas/project/inkscape/22x22/actions/align-vertical-bottom.png"
+   inkscape:export-xdpi="90"
+   inkscape:export-ydpi="90"
+   sodipodi:modified="true">
+  <defs
+     id="defs10701">
+    <linearGradient
+       id="linearGradient2968"
+       inkscape:collect="always">
+      <stop
+         id="stop2970"
+         offset="0"
+         style="stop-color:#ce5c00;stop-opacity:1" />
+      <stop
+         id="stop2972"
+         offset="1"
+         style="stop-color:#ce5c00;stop-opacity:0" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2968"
+       id="linearGradient6954"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-1,0,0,-1,395.9999,981)"
+       x1="187.60938"
+       y1="489.35938"
+       x2="186.93732"
+       y2="489.35938" />
+    <linearGradient
+       id="linearGradient2974"
+       inkscape:collect="always">
+      <stop
+         id="stop2976"
+         offset="0"
+         style="stop-color:#fcaf3e;stop-opacity:1" />
+      <stop
+         id="stop2978"
+         offset="1"
+         style="stop-color:#fcaf3e;stop-opacity:0" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2974"
+       id="linearGradient6952"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-1,0,0,-1,395.9999,981)"
+       x1="187.81554"
+       y1="489.54688"
+       x2="187.1716"
+       y2="489.54688" />
+    <linearGradient
+       id="linearGradient2986"
+       inkscape:collect="always">
+      <stop
+         id="stop2988"
+         offset="0"
+         style="stop-color:#ce5c00;stop-opacity:1" />
+      <stop
+         id="stop2990"
+         offset="1"
+         style="stop-color:#ce5c00;stop-opacity:0" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2986"
+       id="linearGradient6950"
+       gradientUnits="userSpaceOnUse"
+       x1="187.60938"
+       y1="489.35938"
+       x2="186.93732"
+       y2="489.35938" />
+    <linearGradient
+       id="linearGradient2980"
+       inkscape:collect="always">
+      <stop
+         id="stop2982"
+         offset="0"
+         style="stop-color:#fcaf3e;stop-opacity:1" />
+      <stop
+         id="stop2984"
+         offset="1"
+         style="stop-color:#fcaf3e;stop-opacity:0" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2980"
+       id="linearGradient6948"
+       gradientUnits="userSpaceOnUse"
+       x1="187.81554"
+       y1="489.54688"
+       x2="187.1716"
+       y2="489.54688" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="11.197802"
+     inkscape:cx="16"
+     inkscape:cy="16"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:grid-bbox="true"
+     inkscape:document-units="px"
+     width="22px"
+     height="22px"
+     inkscape:window-width="797"
+     inkscape:window-height="628"
+     inkscape:window-x="0"
+     inkscape:window-y="47" />
+  <metadata
+     id="metadata10704">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer">
+    <g
+       style="display:inline"
+       id="g6862"
+       transform="translate(-59.99998,90)"
+       inkscape:export-filename="/home/lapo/Desktop/align-distribute.tar.gz_FILES/align-stuff.png"
+       inkscape:export-xdpi="90"
+       inkscape:export-ydpi="90">
+      <g
+         id="g3084"
+         transform="translate(-97,-563)"
+         style="fill:#d3d7cf;stroke:#888a85"
+         inkscape:export-filename="/home/lapo/Desktop/align-distribute.tar.gz_FILES/align-stuff.png"
+         inkscape:export-xdpi="90"
+         inkscape:export-ydpi="90">
+        <rect
+           transform="matrix(0,1,1,0,0,0)"
+           y="169.5"
+           x="475.50012"
+           height="7"
+           width="12"
+           id="rect3086"
+           style="fill:#d3d7cf;fill-opacity:1;stroke:#888a85;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:3;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+        <rect
+           ry="0"
+           rx="0"
+           transform="matrix(0,1,1,0,0,0)"
+           y="170.5"
+           x="476.50012"
+           height="5.0000305"
+           width="10"
+           id="rect3088"
+           style="opacity:1;fill:#d3d7cf;fill-opacity:1;stroke:#ffffff;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+      </g>
+      <g
+         id="g3090"
+         transform="translate(-67,-559)"
+         inkscape:export-filename="/home/lapo/Desktop/align-distribute.tar.gz_FILES/align-stuff.png"
+         inkscape:export-xdpi="90"
+         inkscape:export-ydpi="90">
+        <rect
+           transform="matrix(0,-1,1,0,0,0)"
+           y="129.49626"
+           x="-489.49979"
+           height="7.0035982"
+           width="17.999748"
+           id="rect3092"
+           style="color:#000000;fill:#d3d7cf;fill-opacity:1;fill-rule:evenodd;stroke:#888a85;stroke-width:1.00024867;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline" />
+        <rect
+           transform="matrix(0,-1,1,0,0,0)"
+           y="130.50006"
+           x="-488.50009"
+           height="4.9998937"
+           width="15.999757"
+           id="rect3094"
+           style="color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.00024891;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:2;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+           rx="0"
+           ry="0" />
+      </g>
+      <g
+         id="g3262"
+         transform="translate(-127,-578)"
+         inkscape:export-filename="/home/lapo/Desktop/align-distribute.tar.gz_FILES/align-stuff.png"
+         inkscape:export-xdpi="90"
+         inkscape:export-ydpi="90">
+        <rect
+           y="489.5"
+           x="196.49989"
+           height="1.9999999"
+           width="3.0000916"
+           id="rect3264"
+           style="fill:#fcaf3e;fill-opacity:1;stroke:#ce5c00;stroke-width:0.99999976;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+        <path
+           style="fill:url(#linearGradient6948);fill-opacity:1;stroke:url(#linearGradient6950);stroke-width:0.99999976;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:0;stroke-dashoffset:0;stroke-opacity:1"
+           d="M 197.49998,491.5 L 186.49989,491.5 L 186.49989,489.5 L 197.49998,489.5"
+           id="path3266"
+           sodipodi:nodetypes="cccc" />
+        <path
+           style="fill:url(#linearGradient6952);fill-opacity:1;stroke:url(#linearGradient6954);stroke-width:0.99999976;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:0;stroke-dashoffset:0;stroke-opacity:1"
+           d="M 198.49989,489.5 L 209.49998,489.5 L 209.49998,491.5 L 198.49989,491.5"
+           id="path3268"
+           sodipodi:nodetypes="cccc" />
+      </g>
+    </g>
+  </g>
+</svg>

BIN
main/inc/lib/svg-edit/images/bold.png


BIN
main/inc/lib/svg-edit/images/cancel.png


BIN
main/inc/lib/svg-edit/images/circle.png


BIN
main/inc/lib/svg-edit/images/clear.png


BIN
main/inc/lib/svg-edit/images/clone.png


+ 29 - 0
main/inc/lib/svg-edit/images/conn.svg

@@ -0,0 +1,29 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+	<g id="mode_connect">
+		<svg viewBox="0 0 24 24" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg">
+		 <defs>
+
+		  <line stroke-width="5" fill="none" stroke="#000000" id="svg_2" y2="121" x2="136" y1="7" x1="136">
+		   <stop stop-opacity="1" stop-color="#4687a0"/>
+		   <stop stop-opacity="1" stop-color="#ffffff"/>
+		  </line>
+		  <linearGradient y2="0.18359" x2="0.29688" y1="0.92188" x1="0.62109" id="svg_3">
+		   <stop stop-opacity="1" stop-color="#417dad" offset="0"/>
+		   <stop stop-opacity="1" stop-color="#ffffff" offset="1"/>
+		  </linearGradient>
+		 </defs>
+		 <g>
+		  <title>Layer 1</title>
+		  <line x1="5.64676" y1="5.60056" x2="18.50037" y2="18.62557" id="svg_5" stroke="#000000" fill="none"/>
+		  <rect opacity="0.75" stroke-width="0.5" x="0.5" y="0.5" width="9.625" height="5.125" id="svg_1" fill="url(#svg_3)" stroke="#000000"/>
+		  <rect opacity="0.75" id="svg_4" stroke-width="0.5" x="13.75" y="18.25" width="9.625" height="5.125" fill="url(#svg_3)" stroke="#000000"/>
+		  <g id="svg_9">
+		   <path d="m14.57119,9.12143l-0.98244,5.18852l2.70861,-4.36084" id="svg_6" fill="#a0a0a0" stroke="#000000"/>
+		   <path d="m14.27564,6.76258c-0.25872,0.72562 -0.40735,1.65632 -0.33812,2.15432l2.90784,1.2509c0.30961,-0.21212 1.08198,-1.1814 1.08198,-1.73736" id="svg_7" fill="url(#svg_3)" stroke="#000000"/>
+		   <path d="m16.28893,0.37519l-2.46413,5.9304l4.76481,2.39435l2.13178,-4.96735" id="svg_8" fill="url(#svg_3)" stroke="#000000"/>
+		  </g>
+		 </g>
+		</svg>
+	</g>
+	<g id="svg_eof"/>
+</svg>

BIN
main/inc/lib/svg-edit/images/copy.png


BIN
main/inc/lib/svg-edit/images/cut.png


BIN
main/inc/lib/svg-edit/images/delete.png


BIN
main/inc/lib/svg-edit/images/document-properties.png


BIN
main/inc/lib/svg-edit/images/dropdown.gif


BIN
main/inc/lib/svg-edit/images/ellipse.png


BIN
main/inc/lib/svg-edit/images/eye.png


BIN
main/inc/lib/svg-edit/images/fhpath.png


BIN
main/inc/lib/svg-edit/images/flyouth.png


BIN
main/inc/lib/svg-edit/images/flyup.gif


BIN
main/inc/lib/svg-edit/images/freehand-circle.png


BIN
main/inc/lib/svg-edit/images/freehand-square.png


BIN
main/inc/lib/svg-edit/images/go-down.png


BIN
main/inc/lib/svg-edit/images/go-up.png


BIN
main/inc/lib/svg-edit/images/image.png


BIN
main/inc/lib/svg-edit/images/italic.png


BIN
main/inc/lib/svg-edit/images/line.png


BIN
main/inc/lib/svg-edit/images/link_controls.png


BIN
main/inc/lib/svg-edit/images/logo.png


Файловите разлики са ограничени, защото са твърде много
+ 18 - 0
main/inc/lib/svg-edit/images/logo.svg


BIN
main/inc/lib/svg-edit/images/move_bottom.png


BIN
main/inc/lib/svg-edit/images/move_top.png


BIN
main/inc/lib/svg-edit/images/node_clone.png


BIN
main/inc/lib/svg-edit/images/node_delete.png


BIN
main/inc/lib/svg-edit/images/none.png


BIN
main/inc/lib/svg-edit/images/open.png


BIN
main/inc/lib/svg-edit/images/paste.png


BIN
main/inc/lib/svg-edit/images/path.png


BIN
main/inc/lib/svg-edit/images/polygon.png


+ 219 - 0
main/inc/lib/svg-edit/images/polygon.svg

@@ -0,0 +1,219 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   sodipodi:docname="draw-polygon.svg"
+   sodipodi:docbase="/home/andreas/projekt/tango/22"
+   inkscape:version="0.42"
+   id="svg8728"
+   height="22.000000px"
+   width="22.000000px"
+   inkscape:export-filename="/home/andreas/projekt/tango/22/draw-polygon.png"
+   inkscape:export-xdpi="90.000000"
+   inkscape:export-ydpi="90.000000">
+  <defs
+     id="defs3">
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient3941">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop3943" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop3945" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient6581">
+      <stop
+         style="stop-color:#eeeeec;stop-opacity:1;"
+         offset="0"
+         id="stop6583" />
+      <stop
+         style="stop-color:#e0e0de;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop6585" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient14920">
+      <stop
+         id="stop14922"
+         offset="0"
+         style="stop-color:#5a7aa4;stop-opacity:1;" />
+      <stop
+         id="stop14924"
+         offset="1.0000000"
+         style="stop-color:#1f2b3a;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient13390">
+      <stop
+         id="stop13392"
+         offset="0.0000000"
+         style="stop-color:#81a2cd;stop-opacity:1.0000000;" />
+      <stop
+         id="stop13394"
+         offset="1.0000000"
+         style="stop-color:#2a415f;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient10325">
+      <stop
+         id="stop10327"
+         offset="0"
+         style="stop-color:#5a7aa4;stop-opacity:1;" />
+      <stop
+         id="stop10329"
+         offset="1.0000000"
+         style="stop-color:#455e7e;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="39.486301"
+       x2="37.746555"
+       y1="23.992306"
+       x1="23.598076"
+       gradientTransform="matrix(0.363308,0,0,0.363571,1.976073,1.180651)"
+       id="linearGradient13217"
+       xlink:href="#linearGradient6581"
+       inkscape:collect="always" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3941"
+       id="radialGradient3947"
+       cx="2.25"
+       cy="16"
+       fx="2.25"
+       fy="16"
+       r="16.875"
+       gradientTransform="matrix(1.000000,0.000000,0.000000,0.333333,-5.774893e-15,10.66667)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6581"
+       id="linearGradient2398"
+       x1="10.769515"
+       y1="8.7196503"
+       x2="15.923767"
+       y2="15.039417"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6581"
+       id="linearGradient2403"
+       gradientUnits="userSpaceOnUse"
+       x1="10.769515"
+       y1="8.7196503"
+       x2="15.923767"
+       y2="15.039417"
+       gradientTransform="matrix(0.874941,0.000000,0.000000,0.868551,1.339139,1.349650)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6581"
+       id="linearGradient2405"
+       gradientUnits="userSpaceOnUse"
+       x1="10.769515"
+       y1="8.7196503"
+       x2="15.923767"
+       y2="15.039417"
+       gradientTransform="matrix(1.001575,0.000000,0.000000,1.000000,-3.040037e-3,0.000000)" />
+  </defs>
+  <sodipodi:namedview
+     inkscape:window-y="25"
+     inkscape:window-x="0"
+     inkscape:window-height="949"
+     inkscape:window-width="1280"
+     inkscape:document-units="px"
+     inkscape:grid-bbox="true"
+     showgrid="false"
+     inkscape:current-layer="layer1"
+     inkscape:cy="10.249014"
+     inkscape:cx="16.435231"
+     inkscape:zoom="15.999999"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     borderopacity="0.08235294"
+     bordercolor="#666666"
+     pagecolor="#ffffff"
+     id="base"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:showpageshadow="false"
+     stroke="#888a85" />
+  <metadata
+     id="metadata4">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title>Draw Rectangle</dc:title>
+        <dc:date>2005-10-10</dc:date>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>Andreas Nilsson</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>draw</rdf:li>
+            <rdf:li>rectangle</rdf:li>
+            <rdf:li>square</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/Reproduction" />
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/Distribution" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/Notice" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/Attribution" />
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/ShareAlike" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:groupmode="layer"
+     inkscape:label="Layer 1"
+     id="layer1">
+    <path
+       sodipodi:type="arc"
+       style="opacity:0.60000000;color:#000000;fill:url(#radialGradient3947);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:block;overflow:visible"
+       id="path2193"
+       sodipodi:cx="2.2500000"
+       sodipodi:cy="16.000000"
+       sodipodi:rx="16.875000"
+       sodipodi:ry="5.6250000"
+       d="M 19.125000 16.000000 A 16.875000 5.6250000 0 1 1  -14.625000,16.000000 A 16.875000 5.6250000 0 1 1  19.125000 16.000000 z"
+       transform="matrix(0.503704,0.000000,0.000000,0.349014,9.366667,12.45257)" />
+    <path
+       style="fill:url(#linearGradient2405);fill-opacity:1.0000000;fill-rule:evenodd;stroke:#888a85;stroke-width:1.0000002px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+       d="M 10.376363,3.6237647 L 18.439333,9.5822222 L 15.644242,18.503298 L 5.3933717,18.503298 L 2.5694122,9.5814367 L 10.376363,3.6237647 z "
+       id="path1661"
+       sodipodi:nodetypes="cccccc" />
+    <path
+       style="fill:url(#linearGradient2403);fill-opacity:1.0000000;fill-rule:evenodd;stroke:#fdfdfb;stroke-width:0.99999976px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+       d="M 10.383801,4.6223366 L 17.428917,9.8682235 L 14.894231,17.502140 L 6.1335005,17.494329 L 3.6135882,9.9131875 L 10.383801,4.6223366 z "
+       id="path2401"
+       sodipodi:nodetypes="cccccc" />
+  </g>
+</svg>

BIN
main/inc/lib/svg-edit/images/rect.png


BIN
main/inc/lib/svg-edit/images/redo.png


BIN
main/inc/lib/svg-edit/images/reorient.png


BIN
main/inc/lib/svg-edit/images/rotate.png


BIN
main/inc/lib/svg-edit/images/save.png


BIN
main/inc/lib/svg-edit/images/select.png


BIN
main/inc/lib/svg-edit/images/select_node.png


BIN
main/inc/lib/svg-edit/images/sep.png


BIN
main/inc/lib/svg-edit/images/shape_group.png


BIN
main/inc/lib/svg-edit/images/shape_ungroup.png


BIN
main/inc/lib/svg-edit/images/source.png


BIN
main/inc/lib/svg-edit/images/spinbtn_updn_big.png


BIN
main/inc/lib/svg-edit/images/square.png


Файловите разлики са ограничени, защото са твърде много
+ 21 - 0
main/inc/lib/svg-edit/images/svg_edit_icons.svg


BIN
main/inc/lib/svg-edit/images/svg_edit_icons.svgz


BIN
main/inc/lib/svg-edit/images/text.png


+ 157 - 0
main/inc/lib/svg-edit/images/text.svg

@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="22.000000px"
+   height="22.000000px"
+   id="svg1306"
+   sodipodi:version="0.32"
+   inkscape:version="0.42.2"
+   sodipodi:docbase="/home/andreas/projekt/bild/tango/22"
+   sodipodi:docname="draw-text2.svg">
+  <defs
+     id="defs1308">
+    <linearGradient
+       id="linearGradient3682">
+      <stop
+         style="stop-color:#1f1f1f;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop3684" />
+      <stop
+         style="stop-color:#5c5c5c;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop3686" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient3558">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop3560" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop3562" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3558"
+       id="radialGradient3564"
+       cx="22.571428"
+       cy="30.857143"
+       fx="22.571428"
+       fy="30.857143"
+       r="15.571428"
+       gradientTransform="matrix(1.000000,0.000000,0.000000,0.651376,4.300378e-15,10.75754)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       id="linearGradient2834">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop2836" />
+      <stop
+         style="stop-color:#b3b3b3;stop-opacity:0.0000000;"
+         offset="1.0000000"
+         id="stop2838" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2834"
+       id="linearGradient2840"
+       x1="19.944447"
+       y1="16.527262"
+       x2="24.133829"
+       y2="19.642126"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.498259,0.000000,0.000000,0.466519,-0.799974,-0.839637)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3682"
+       id="linearGradient3688"
+       x1="23.305620"
+       y1="24.843527"
+       x2="14.388516"
+       y2="9.5902243"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.498259,0.000000,0.000000,0.488600,-0.799974,-1.273557)" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="14.000000"
+     inkscape:cx="17.541947"
+     inkscape:cy="12.572768"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:grid-bbox="true"
+     inkscape:document-units="px"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:window-width="1280"
+     inkscape:window-height="885"
+     inkscape:window-x="0"
+     inkscape:window-y="25" />
+  <metadata
+     id="metadata1311">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer">
+    <path
+       sodipodi:type="arc"
+       style="opacity:0.47368422;color:#000000;fill:url(#radialGradient3564);fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"
+       id="path3556"
+       sodipodi:cx="22.571428"
+       sodipodi:cy="30.857143"
+       sodipodi:rx="15.571428"
+       sodipodi:ry="10.142858"
+       d="M 38.142857 30.857143 A 15.571428 10.142858 0 1 1  7.0000000,30.857143 A 15.571428 10.142858 0 1 1  38.142857 30.857143 z"
+       transform="matrix(0.706422,0.000000,0.000000,0.208015,-4.944952,13.47138)" />
+    <path
+       style="font-size:54.869392px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;fill:url(#linearGradient3688);fill-opacity:1.0000000;stroke:#000000;stroke-width:1.0000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+       d="M 15.189363,15.520771 L 7.1531447,15.520771 L 5.8598048,19.513834 L 0.51627279,19.513834 L 8.1009381,0.48837876 L 14.228221,0.48837876 L 21.560524,19.464779 L 16.444188,19.464779 L 15.189363,15.520771 M 8.3990779,12.473977 L 13.858901,12.473977 L 11.171254,5.1526958 L 8.3990779,12.473977"
+       id="text1314"
+       sodipodi:nodetypes="ccccccccccccc" />
+    <path
+       style="font-size:54.869392px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;opacity:0.37912086;fill:none;fill-opacity:1.0000000;stroke:url(#linearGradient2840);stroke-width:1.0000008;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+       d="M 15.684541,15.159554 L 6.6710758,15.159554 L 5.4166733,18.527305 L 2.0035414,18.527305 L 8.7384662,1.4621947 L 13.512484,1.4621947 L 20.022564,18.410463 L 16.899702,18.410463 L 15.684541,15.159554 z "
+       id="path2047"
+       sodipodi:nodetypes="ccccccccc" />
+    <image
+       id="image2089"
+       height="459.00000"
+       width="400.00000"
+       sodipodi:absref="/home/andreas/palette2.png"
+       xlink:href="/home/andreas/palette2.png"
+       x="-354.93631"
+       y="-214.53793" />
+    <path
+       style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#999999;stroke-width:1.0000007;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000;opacity:0.51098901"
+       d="M 8.1686844,13.551882 L 14.147791,13.551882"
+       id="path5142"
+       sodipodi:nodetypes="cc" />
+  </g>
+</svg>

BIN
main/inc/lib/svg-edit/images/to_path.png


BIN
main/inc/lib/svg-edit/images/undo.png


BIN
main/inc/lib/svg-edit/images/view-refresh.png


BIN
main/inc/lib/svg-edit/images/wave.png


BIN
main/inc/lib/svg-edit/images/wireframe.png


BIN
main/inc/lib/svg-edit/images/zoom.png


+ 202 - 0
main/inc/lib/svg-edit/jgraduate/LICENSE

@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 3 - 0
main/inc/lib/svg-edit/jgraduate/README

@@ -0,0 +1,3 @@
+jGraduate - A jQuery plugin for picking gradients
+
+Licensed under the Apache License 2.  See LICENSE for more information.

+ 191 - 0
main/inc/lib/svg-edit/jgraduate/css/jPicker-1.0.12.css

@@ -0,0 +1,191 @@
+.jPicker_Picker {
+  display: inline-block;
+  height: 24px; /* change this value if using a different sized color picker icon */
+  position: relative; /* make this element an absolute positioning container */
+  text-align: left; /* make the zero width children position to the left of container */
+  width: 25px; /* change this value if using a different sized color picker icon */
+}
+.jPicker_Color, .jPicker_Alpha {
+  background-position: 2px 2px;
+  display: block;
+  height: 100%;
+  left: 0px;
+  position: absolute;
+  top: 0px;
+  width: 100%;
+}
+.jPicker_Icon {
+  background-repeat: no-repeat;
+  cursor: pointer;
+  display: block;
+  height: 100%;
+  left: 0px;
+  position: absolute;
+  top: 0px;
+  width: 100%;
+}
+.jPicker_Container {
+  display: none;
+  z-index: 10; /* make sure container draws above color picker icon in Firefox/Safari/Chrome/Opera/etc. -
+                  IE calculates z-index so this won't work - we will hide all color picker icons placed after the selected one in code when shown in IE */
+}
+.jPicker_table {
+  background-color: #efefef;
+  border: 1px outset #666;
+  font-family: Arial, Helvetica, Sans-Serif;
+  font-size: 12px;
+  margin: 0px;
+  padding: 5px;
+  width: 550px;
+}
+.jPicker_table td {
+  margin: 0px;
+  padding: 0px;
+  vertical-align: top;
+}
+.jPicker_MoveBar {
+  background-color: #dddddd;
+  border: 1px outset #aaa;
+  cursor: move;
+  height: 12px;
+}
+.jPicker_Title {
+  font-size: 11px !important;
+  font-weight: bold;
+  margin: -2px 0px 0px 0px;
+  padding: 0px;
+  text-align: center;
+  width: 100%;
+}
+.jPicker_ColorMap {
+  border: 2px inset #eee;
+  cursor: crosshair;
+  height: 260px; /* IE 6 incorrectly draws border inside the width and height instead of outside - We will fix this to 256px later */
+  margin: 0px 5px 0px 5px;
+  overflow: hidden; /* hide the overdraw of the Color Map icon when at edge of viewing box */
+  padding: 0px;
+  position: relative; /* make this element an absolute positioning container */
+  width: 260px; /* IE 6 incorrectly draws border inside the width and height instead of outside - We will fix this to 256px later */
+}
+div[class="jPicker_ColorMap"] {
+  height: 256px; /* correct to 256px for browsers that support the "[class="xxx"]" selector (IE7+,Firefox,Safari,Chrome,Opera,etc.) */
+  width: 256px; /* correct to 256px for browsers that support the "[class="xxx"]" selector (IE7+,Firefox,Safari,Chrome,Opera,etc.) */
+}
+.jPicker_ColorBar {
+  border: 2px inset #eee;
+  cursor: n-resize;
+  height: 260px; /* IE 6 incorrectly draws border inside the width and height instead of outside - We will fix this to 256px later */
+  margin: 12px 10px 0px 5px;
+  padding: 0px;
+  position: relative;
+  width: 24px; /* IE 6 incorrectly draws border inside the width and height instead of outside - We will fix this to 20px later */
+}
+div[class="jPicker_ColorBar"] {
+  height: 256px; /* correct to 256px for browsers that support the "[class="xxx"]" selector (IE7+,Firefox,Safari,Chrome,Opera,etc.) */
+  width: 20px; /* correct to 20px for browsers that support the "[class="xxx"]" selector (IE7+,Firefox,Safari,Chrome,Opera,etc.) */
+}
+.jPicker_ColorMap_l1, .jPicker_ColorMap_l2, .jPicker_ColorMap_l3, .jPicker_ColorBar_l1, .jPicker_ColorBar_l2, .jPicker_ColorBar_l3, .jPicker_ColorBar_l4, .jPicker_ColorBar_l5, .jPicker_ColorBar_l6 {
+  background-color: transparent;
+  background-image: none;
+  display: block;
+  height: 256px; /* must specific pixel height. IE7/8 Quirks mode ignores opacity for an absolutely positioned item in a relative container with "overflow: visible". The marker in the colorBar
+                    would not be drawn if its overflow is set to hidden. */
+  left: 0px;
+  position: absolute;
+  top: 0px;
+}
+.jPicker_ColorMap_l1, .jPicker_ColorMap_l2, .jPicker_ColorMap_l3 {
+  width: 256px; /* must specific pixel width. IE7/8 Quirks mode ignores opacity for an absolutely positioned item in a relative container with "overflow: visible". The marker in the colorBar
+                   would not be drawn if its overflow is set to hidden. */
+}
+.jPicker_ColorBar_l1, .jPicker_ColorBar_l2, .jPicker_ColorBar_l3, .jPicker_ColorBar_l4, .jPicker_ColorBar_l5, .jPicker_ColorBar_l6 {
+  width: 20px; /* must specific pixel width. IE7/8 Quirks mode ignores opacity for an absolutely positioned item in a relative container with "overflow: visible". The marker in the colorBar
+                  would not be drawn if its overflow is set to hidden. */
+}
+.jPicker_ColorMap_l1, .jPicker_ColorMap_l2, .jPicker_ColorBar_l6 {
+  background-repeat: no-repeat;
+}
+.jPicker_ColorMap_l3, .jPicker_ColorBar_l5 {
+  background-repeat: repeat;
+}
+.jPicker_ColorBar_l1, .jPicker_ColorBar_l2, .jPicker_ColorBar_l3, .jPicker_ColorBar_l4 {
+  background-repeat: repeat-x;
+}
+.jPicker_ColorMap_Arrow {
+  display: block;
+  position: absolute;
+}
+.jPicker_ColorBar_Arrow {
+  display: block;
+  left: -10px; /* (arrow width / 2) - (element width / 2) - position arrows' center in elements' center */
+  position: absolute;
+}
+.jPicker_Preview {
+  font-size: x-small;
+  text-align: center;
+}
+.jPicker_Preview div {
+  border: 2px inset #eee;
+  height: 62px;
+  margin: 0px auto;
+  padding: 0px;
+  width: 62px;
+}
+.jPicker_Preview div span {
+  border: 1px solid #000;
+  display: block;
+  height: 30px;
+  margin: 0px auto;
+  padding: 0px;
+  width: 60px;
+}
+.jPicker_Preview div span.jPicker_Active {
+  border-bottom-width: 0px;
+}
+.jPicker_Preview div span.jPicker_Current {
+  border-top-width: 0px;
+  cursor: pointer;
+}
+.jPicker_OkCancel {
+  text-align: center;
+  width: 120px;
+}
+.jPicker_OkCancel input {
+  width: 100px;
+}
+.jPicker_OkCancel input.jPicker_Ok {
+  margin: 12px 0px 5px 0px;
+}
+.jPicker_Text {
+  text-align: left;
+}
+.jPicker_HueText, .jPicker_SaturationText, .jPicker_BrightnessText, .jPicker_RedText, .jPicker_GreenText, .jPicker_BlueText, .jPicker_AlphaText {
+  background-color: #fff;
+  border: 1px inset #aaa;
+  margin: 0px 0px 0px 5px;
+  text-align: left;
+  width: 30px;
+}
+.jPicker_HexText {
+  background-color: #fff;
+  border: 1px inset #aaa;
+  margin: 0px 0px 0px 5px;
+  width: 65px;
+}
+.jPicker_Grid {
+  text-align: center;
+}
+span.jPicker_QuickColor {
+  border: 1px inset #aaa;
+  cursor: pointer;
+  display: block;
+  float: left;
+  height: 13px;
+  line-height: 13px;
+  margin: 2px 2px 1px 2px;
+  padding: 0px;
+  width: 15px;
+}
+span[class="jPicker_QuickColor"] {
+  width: 13px;
+}

+ 270 - 0
main/inc/lib/svg-edit/jgraduate/css/jgraduate.css

@@ -0,0 +1,270 @@
+/* 
+ * jGraduate Default CSS
+ * 
+ * Copyright (c) 2009 Jeff Schiller
+ *
+ * Licensed under the Apache License Version 2
+ */
+
+h2.jGraduate_Title {
+  font-family: Arial, Helvetica, Sans-Serif;
+  font-size: 11px !important;
+  font-weight: bold;
+  margin: -13px 0px 0px 0px;
+  padding: 0px;
+  text-align: center;
+}
+
+.jGraduate_Picker {
+	font-family: Arial, Helvetica, Sans-Serif;
+	font-size: 12px;
+	border-style: solid;
+	border-color: lightgrey black black lightgrey;
+	border-width: 1px;
+	background-color: #EFEFEF;
+	position: absolute;
+	padding: 10px;
+}
+
+.jGraduate_tabs li {
+	background-color: #ccc;
+	display: inline;
+	border: solid 1px grey;
+	padding: 3px;
+	margin: 2px;
+	cursor: pointer;
+}
+
+li.jGraduate_tab_current {
+	background-color: #EFEFEF;
+	display: inline;
+	padding: 3px;
+	margin: 2px;
+	border: solid 1px black;
+	cursor: pointer;
+}
+
+.jGraduate_colPick {
+	display: none;
+}
+
+.jGraduate_lgPick {	
+	display: none;
+	border: outset 1px #666;
+	padding: 10px 7px 5px 5px;
+	overflow: auto;
+}
+
+.jGraduate_rgPick {	
+	display: none;
+	border: outset 1px #666;
+	padding: 10px 7px 5px 5px;
+	overflow: auto;
+/*	position: relative;*/
+}
+
+.jGraduate_tabs {
+	position: relative;
+	background-color: #EFEFEF;
+	padding: 0px;
+	margin: 0px;
+	margin-bottom: 5px;
+}
+
+div.jGraduate_Swatch {
+	float: left;
+	margin: 8px;
+}
+div.jGraduate_GradContainer {
+	border: 2px inset #EEE;
+	background-image: url(../images/map-opacity.png); 
+	background-position: 0px 0px;
+	height: 256px;
+}
+
+.jGraduate_AlphaArrows {
+	position: absolute;
+	margin-top: -10px;
+	margin-left: 250.5px;
+}
+
+div.jGraduate_Opacity {
+	border: 2px inset #eee;
+	margin-top: 14px;
+	background-color: black;
+	background-image: url(../images/Maps.png);
+	background-position: 0px -2816px;
+	height: 20px;
+	cursor: ew-resize;
+}
+
+div.lg_jGraduate_OpacityField {
+	position: absolute;
+	bottom: 25px;
+	left: 292px;
+}
+
+div.jGraduate_Form {
+	float: left;
+	width: 140px;
+	margin: -3px 3px 0px 4px;
+}
+
+div.jGraduate_StopSection {
+	width: 120px;
+	text-align: center;
+}
+
+div.jGraduate_RadiusField {
+	
+	text-align: center;
+	float: left;
+}
+
+div.jGraduate_RadiusField input {
+	margin-top: 10px;
+}
+
+.jGraduate_RadiusField .jGraduate_Form_Section {
+	width: 250px;
+	padding: 2px;
+	height: 80px;
+	overflow: visible;
+}
+
+.jGraduate_Form_Section input[type=text] {
+	width: 38px;
+}
+
+.jGraduate_Radius {
+	border:1px solid #BBB;
+	cursor:ew-resize;
+	height:20px;
+	margin-top:14px;
+	position: relative;
+}
+
+
+.jGraduate_RadiusArrows {
+	top: 0;
+	left: 0;
+	position: absolute;
+	margin-top: -10px;
+	margin-left: 250.5px;
+}
+
+
+div.jGraduate_OkCancel {
+	float: left;
+	width: 113px;
+}
+
+input.jGraduate_Ok, input.jGraduate_Cancel {
+	display: block;
+	width: 100px;
+	margin-left: -4px;
+	margin-right: -4px;
+}
+input.jGraduate_Ok {
+	margin: 9px -4px 5px -4px;
+}
+
+.colorBox {
+	float: left;
+	height: 16px;
+	width: 16px;
+	border: 1px solid #808080;
+	cursor: pointer;
+	margin: 4px 4px 4px 30px;
+}
+
+.colorBox + label {
+	float: left;
+	margin-top: 7px;
+}
+
+label.jGraduate_Form_Heading {
+	position: relative;
+	top: 10px;
+	background-color: #EFEFEF;
+	padding: 2px;
+	font-weight: bold;
+	font-size: 13px;
+}
+
+div.jGraduate_Form_Section {
+	border-style: solid;
+	border-width: 1px;
+	border-color: grey;
+	-moz-border-radius: 5px;
+	-webkit-border-radius: 5px;
+	padding: 15px 5px 5px 5px;
+	margin: 2px;
+	width: 110px;
+	text-align: center;
+	overflow: auto;
+}
+
+div.jGraduate_LightBox {
+	position: fixed;
+	top: 0px;
+	left: 0px;
+	right: 0px;
+	bottom: 0px;
+	background-color: #000;
+	opacity: 0.5;
+	display: none;
+}
+
+div.jGraduate_stopPicker {
+	position: absolute;
+	display: none;
+	background: #E8E8E8;
+}
+
+
+.jGraduate_rgPick {
+	width: 530px;
+}
+
+.jGraduate_rgPick div.jGraduate_Form {
+	width: 270px;
+	position: absolute;
+	left: 284px;
+	width: 266px;
+	top: 130px;
+	margin: -3px 3px 0px 4px;
+}
+
+.jGraduate_Colorblocks {
+	display: table;
+	border-spacing: 0 5px;
+}
+
+.jGraduate_colorblock {
+	display: table-row;
+}
+
+.jGraduate_Colorblocks .jGraduate_colorblock > * {
+	display: table-cell;
+	vertical-align: middle;
+	margin: 0;
+	float: none;
+}
+
+.jGraduate_rgPick div.jGraduate_StopSection {
+	float: left;
+	width: 133px;
+	margin: 0;
+}
+
+.jGraduate_rgPick .jGraduate_OkCancel {
+	position: absolute;
+	right: 0;
+}
+
+.rg_jGraduate_OpacityField {
+	position: absolute;
+	left: 288px;
+	bottom: 24px;
+}

BIN
main/inc/lib/svg-edit/jgraduate/images/AlphaBar.png


BIN
main/inc/lib/svg-edit/jgraduate/images/Bars.png


BIN
main/inc/lib/svg-edit/jgraduate/images/Maps.png


BIN
main/inc/lib/svg-edit/jgraduate/images/NoColor.png


BIN
main/inc/lib/svg-edit/jgraduate/images/bar-opacity.png


Някои файлове не бяха показани, защото твърде много файлове са промени