Merge branch 'bzr/golem' of /Users/distler/Sites/code/instiki
This commit is contained in:
commit
04bb80be15
|
@ -11,11 +11,29 @@ if(!window.console) {
|
|||
window.console.log = function(str) {};
|
||||
window.console.dir = function(str) {};
|
||||
}
|
||||
|
||||
// <3 IE
|
||||
if(!Array.indexOf){
|
||||
Array.prototype.indexOf = function(obj){
|
||||
for(var i=0; i<this.length; i++){
|
||||
if(this[i]==obj){
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
(function(){
|
||||
// canvg(target, s)
|
||||
// target: canvas element or the id of a canvas element
|
||||
// s: svg string or url to svg file
|
||||
this.canvg = function (target, s) {
|
||||
// opts: optional hash of options
|
||||
// ignoreMouse: true => ignore mouse events
|
||||
// ignoreAnimation: true => ignore animations
|
||||
// renderCallback: function => will call the function after the first render is completed
|
||||
// forceRedraw: function => will call the function on every frame, if it returns true, will redraw
|
||||
this.canvg = function (target, s, opts) {
|
||||
if (typeof target == 'string') {
|
||||
target = document.getElementById(target);
|
||||
}
|
||||
|
@ -30,6 +48,7 @@ if(!window.console) {
|
|||
svg = target.svg;
|
||||
svg.stop();
|
||||
}
|
||||
svg.opts = opts;
|
||||
|
||||
var ctx = target.getContext('2d');
|
||||
if (s.substr(0,1) == '<') {
|
||||
|
@ -43,7 +62,7 @@ if(!window.console) {
|
|||
}
|
||||
|
||||
function build() {
|
||||
var svg = {};
|
||||
var svg = { };
|
||||
|
||||
svg.FRAMERATE = 30;
|
||||
|
||||
|
@ -52,6 +71,7 @@ if(!window.console) {
|
|||
svg.Definitions = {};
|
||||
svg.Styles = {};
|
||||
svg.Animations = [];
|
||||
svg.Images = [];
|
||||
svg.ctx = ctx;
|
||||
svg.ViewPort = new (function () {
|
||||
this.viewPorts = [];
|
||||
|
@ -69,6 +89,14 @@ if(!window.console) {
|
|||
});
|
||||
}
|
||||
svg.init();
|
||||
|
||||
// images loaded
|
||||
svg.ImagesLoaded = function() {
|
||||
for (var i=0; i<svg.Images.length; i++) {
|
||||
if (!svg.Images[i].loaded) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// trim
|
||||
svg.trim = function(s) { return s.replace(/^\s+|\s+$/g, ''); }
|
||||
|
@ -290,6 +318,13 @@ if(!window.console) {
|
|||
this.angleTo = function(p) {
|
||||
return Math.atan2(p.y - this.y, p.x - this.x);
|
||||
}
|
||||
|
||||
this.applyTransform = function(v) {
|
||||
var xp = this.x * v[0] + this.y * v[2] + v[4];
|
||||
var yp = this.x * v[1] + this.y * v[3] + v[5];
|
||||
this.x = xp;
|
||||
this.y = yp;
|
||||
}
|
||||
}
|
||||
svg.CreatePoint = function(s) {
|
||||
var a = svg.ToNumberArray(s);
|
||||
|
@ -389,6 +424,10 @@ if(!window.console) {
|
|||
}
|
||||
}
|
||||
|
||||
this.isPointInBox = function(x, y) {
|
||||
return (this.x1 <= x && x <= this.x2 && this.y1 <= y && y <= this.y2);
|
||||
}
|
||||
|
||||
this.addPoint(x1, y1);
|
||||
this.addPoint(x2, y2);
|
||||
}
|
||||
|
@ -404,6 +443,9 @@ if(!window.console) {
|
|||
this.apply = function(ctx) {
|
||||
ctx.translate(this.p.x || 0.0, this.p.y || 0.0);
|
||||
}
|
||||
this.applyToPoint = function(p) {
|
||||
p.applyTransform([1, 0, 0, 1, this.p.x || 0.0, this.p.y || 0.0]);
|
||||
}
|
||||
}
|
||||
|
||||
// rotate
|
||||
|
@ -417,6 +459,12 @@ if(!window.console) {
|
|||
ctx.rotate(this.angle.Angle.toRadians());
|
||||
ctx.translate(-this.cx, -this.cy);
|
||||
}
|
||||
this.applyToPoint = function(p) {
|
||||
var a = this.angle.Angle.toRadians();
|
||||
p.applyTransform([1, 0, 0, 1, this.p.x || 0.0, this.p.y || 0.0]);
|
||||
p.applyTransform([Math.cos(a), Math.sin(a), -Math.sin(a), Math.cos(a), 0, 0]);
|
||||
p.applyTransform([1, 0, 0, 1, -this.p.x || 0.0, -this.p.y || 0.0]);
|
||||
}
|
||||
}
|
||||
|
||||
this.Type.scale = function(s) {
|
||||
|
@ -424,6 +472,9 @@ if(!window.console) {
|
|||
this.apply = function(ctx) {
|
||||
ctx.scale(this.p.x || 1.0, this.p.y || this.p.x || 1.0);
|
||||
}
|
||||
this.applyToPoint = function(p) {
|
||||
p.applyTransform([this.p.x || 0.0, 0, 0, this.p.y || 0.0, 0, 0]);
|
||||
}
|
||||
}
|
||||
|
||||
this.Type.matrix = function(s) {
|
||||
|
@ -431,6 +482,9 @@ if(!window.console) {
|
|||
this.apply = function(ctx) {
|
||||
ctx.transform(this.m[0], this.m[1], this.m[2], this.m[3], this.m[4], this.m[5]);
|
||||
}
|
||||
this.applyToPoint = function(p) {
|
||||
p.applyTransform(this.m);
|
||||
}
|
||||
}
|
||||
|
||||
this.Type.SkewBase = function(s) {
|
||||
|
@ -455,12 +509,19 @@ if(!window.console) {
|
|||
this.Type.skewY.prototype = new this.Type.SkewBase;
|
||||
|
||||
this.transforms = [];
|
||||
|
||||
this.apply = function(ctx) {
|
||||
for (var i=0; i<this.transforms.length; i++) {
|
||||
this.transforms[i].apply(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
this.applyToPoint = function(p) {
|
||||
for (var i=0; i<this.transforms.length; i++) {
|
||||
this.transforms[i].applyToPoint(p);
|
||||
}
|
||||
}
|
||||
|
||||
var data = v.split(/\s(?=[a-z])/);
|
||||
for (var i=0; i<data.length; i++) {
|
||||
var type = data[i].split('(')[0];
|
||||
|
@ -470,6 +531,43 @@ if(!window.console) {
|
|||
}
|
||||
}
|
||||
|
||||
// aspect ratio
|
||||
svg.AspectRatio = function(ctx, aspectRatio, width, desiredWidth, height, desiredHeight, minX, minY, refX, refY) {
|
||||
// aspect ratio - http://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute
|
||||
aspectRatio = svg.compressSpaces(aspectRatio);
|
||||
aspectRatio = aspectRatio.replace(/^defer\s/,''); // ignore defer
|
||||
var align = aspectRatio.split(' ')[0] || 'xMidYMid';
|
||||
var meetOrSlice = aspectRatio.split(' ')[1] || 'meet';
|
||||
|
||||
// calculate scale
|
||||
var scaleX = width / desiredWidth;
|
||||
var scaleY = height / desiredHeight;
|
||||
var scaleMin = Math.min(scaleX, scaleY);
|
||||
var scaleMax = Math.max(scaleX, scaleY);
|
||||
if (meetOrSlice == 'meet') { desiredWidth *= scaleMin; desiredHeight *= scaleMin; }
|
||||
if (meetOrSlice == 'slice') { desiredWidth *= scaleMax; desiredHeight *= scaleMax; }
|
||||
|
||||
refX = new svg.Property('refX', refX);
|
||||
refY = new svg.Property('refY', refY);
|
||||
if (refX.hasValue() && refY.hasValue()) {
|
||||
ctx.translate(-scaleMin * refX.Length.toPixels('x'), -scaleMin * refY.Length.toPixels('y'));
|
||||
}
|
||||
else {
|
||||
// align
|
||||
if (align.match(/^xMid/) && ((meetOrSlice == 'meet' && scaleMin == scaleY) || (meetOrSlice == 'slice' && scaleMax == scaleY))) ctx.translate(width / 2.0 - desiredWidth / 2.0, 0);
|
||||
if (align.match(/YMid$/) && ((meetOrSlice == 'meet' && scaleMin == scaleX) || (meetOrSlice == 'slice' && scaleMax == scaleX))) ctx.translate(0, height / 2.0 - desiredHeight / 2.0);
|
||||
if (align.match(/^xMax/) && ((meetOrSlice == 'meet' && scaleMin == scaleY) || (meetOrSlice == 'slice' && scaleMax == scaleY))) ctx.translate(width - desiredWidth, 0);
|
||||
if (align.match(/YMax$/) && ((meetOrSlice == 'meet' && scaleMin == scaleX) || (meetOrSlice == 'slice' && scaleMax == scaleX))) ctx.translate(0, height - desiredHeight);
|
||||
}
|
||||
|
||||
// scale
|
||||
if (meetOrSlice == 'meet') ctx.scale(scaleMin, scaleMin);
|
||||
if (meetOrSlice == 'slice') ctx.scale(scaleMax, scaleMax);
|
||||
|
||||
// translate
|
||||
ctx.translate(minX == null ? 0 : -minX, minY == null ? 0 : -minY);
|
||||
}
|
||||
|
||||
// elements
|
||||
svg.Element = {}
|
||||
|
||||
|
@ -505,6 +603,9 @@ if(!window.console) {
|
|||
|
||||
// base render
|
||||
this.render = function(ctx) {
|
||||
// don't render display=none
|
||||
if (this.attribute('display').value == 'none') return;
|
||||
|
||||
ctx.save();
|
||||
this.setContext(ctx);
|
||||
this.renderChildren(ctx);
|
||||
|
@ -581,10 +682,14 @@ if(!window.console) {
|
|||
this.styles[name] = new svg.Property(name, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add id
|
||||
if (this.attribute('id').hasValue()) {
|
||||
if (svg.Definitions[this.attribute('id').value] == null) {
|
||||
svg.Definitions[this.attribute('id').value] = this;
|
||||
}
|
||||
}
|
||||
|
||||
// set id
|
||||
if (this.attribute('id').hasValue()) svg.Definitions[this.attribute('id').value] = this;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -660,6 +765,7 @@ if(!window.console) {
|
|||
|
||||
this.renderChildren = function(ctx) {
|
||||
this.path(ctx);
|
||||
svg.Mouse.checkPath(this, ctx);
|
||||
if (ctx.fillStyle != '') ctx.fill();
|
||||
if (ctx.strokeStyle != '') ctx.stroke();
|
||||
|
||||
|
@ -743,36 +849,17 @@ if(!window.console) {
|
|||
width = viewBox[2];
|
||||
height = viewBox[3];
|
||||
|
||||
// aspect ratio - http://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute
|
||||
var preserveAspectRatio = svg.compressSpaces(this.attribute('preserveAspectRatio').value);
|
||||
preserveAspectRatio = preserveAspectRatio.replace(/^defer\s/,''); // ignore defer
|
||||
var align = preserveAspectRatio.split(' ')[0] || 'xMidYMid';
|
||||
var meetOrSlice = preserveAspectRatio.split(' ')[1] || 'meet';
|
||||
|
||||
// calculate scale
|
||||
var scaleX = svg.ViewPort.width() / width;
|
||||
var scaleY = svg.ViewPort.height() / height;
|
||||
var scaleMin = Math.min(scaleX, scaleY);
|
||||
var scaleMax = Math.max(scaleX, scaleY);
|
||||
if (meetOrSlice == 'meet') { width *= scaleMin; height *= scaleMin; }
|
||||
if (meetOrSlice == 'slice') { width *= scaleMax; height *= scaleMax; }
|
||||
|
||||
if (this.attribute('refX').hasValue() && this.attribute('refY').hasValue()) {
|
||||
ctx.translate(-scaleMin * this.attribute('refX').Length.toPixels('x'), -scaleMin * this.attribute('refY').Length.toPixels('y'));
|
||||
}
|
||||
else {
|
||||
// align
|
||||
if (align.match(/^xMid/) && ((meetOrSlice == 'meet' && scaleMin == scaleY) || (meetOrSlice == 'slice' && scaleMax == scaleY))) ctx.translate(svg.ViewPort.width() / 2.0 - width / 2.0, 0);
|
||||
if (align.match(/YMid$/) && ((meetOrSlice == 'meet' && scaleMin == scaleX) || (meetOrSlice == 'slice' && scaleMax == scaleX))) ctx.translate(0, svg.ViewPort.height() / 2.0 - height / 2.0);
|
||||
if (align.match(/^xMax/) && ((meetOrSlice == 'meet' && scaleMin == scaleY) || (meetOrSlice == 'slice' && scaleMax == scaleY))) ctx.translate(svg.ViewPort.width() - width, 0);
|
||||
if (align.match(/YMax$/) && ((meetOrSlice == 'meet' && scaleMin == scaleX) || (meetOrSlice == 'slice' && scaleMax == scaleX))) ctx.translate(0, svg.ViewPort.height() - height);
|
||||
}
|
||||
|
||||
// scale
|
||||
if (meetOrSlice == 'meet') ctx.scale(scaleMin, scaleMin);
|
||||
if (meetOrSlice == 'slice') ctx.scale(scaleMax, scaleMax);
|
||||
ctx.translate(-minX, -minY);
|
||||
|
||||
svg.AspectRatio(ctx,
|
||||
this.attribute('preserveAspectRatio').value,
|
||||
svg.ViewPort.width(),
|
||||
width,
|
||||
svg.ViewPort.height(),
|
||||
height,
|
||||
minX,
|
||||
minY,
|
||||
this.attribute('refX').value,
|
||||
this.attribute('refY').value);
|
||||
|
||||
svg.ViewPort.RemoveCurrent();
|
||||
svg.ViewPort.SetCurrent(viewBox[2], viewBox[3]);
|
||||
}
|
||||
|
@ -920,6 +1007,7 @@ if(!window.console) {
|
|||
|
||||
this.getMarkers = function() {
|
||||
var markers = [];
|
||||
|
||||
for (var i=0; i<this.points.length - 1; i++) {
|
||||
markers.push([this.points[i], this.points[i].angleTo(this.points[i+1])]);
|
||||
}
|
||||
|
@ -969,6 +1057,7 @@ if(!window.console) {
|
|||
this.reset = function() {
|
||||
this.i = -1;
|
||||
this.command = '';
|
||||
this.previousCommand = '';
|
||||
this.control = new svg.Point(0, 0);
|
||||
this.current = new svg.Point(0, 0);
|
||||
this.points = [];
|
||||
|
@ -987,7 +1076,7 @@ if(!window.console) {
|
|||
this.isRelativeCommand = function() {
|
||||
return this.command == this.command.toLowerCase();
|
||||
}
|
||||
|
||||
|
||||
this.getToken = function() {
|
||||
this.i = this.i + 1;
|
||||
return this.tokens[this.i];
|
||||
|
@ -998,6 +1087,7 @@ if(!window.console) {
|
|||
}
|
||||
|
||||
this.nextCommand = function() {
|
||||
this.previousCommand = this.command;
|
||||
this.command = this.getToken();
|
||||
}
|
||||
|
||||
|
@ -1019,8 +1109,13 @@ if(!window.console) {
|
|||
}
|
||||
|
||||
this.getReflectedControlPoint = function() {
|
||||
if (this.previousCommand.toLowerCase() != 'c' && this.previousCommand.toLowerCase() != 's') {
|
||||
return this.current;
|
||||
}
|
||||
|
||||
// reflect point
|
||||
var p = new svg.Point(2 * this.current.x - this.control.x, 2 * this.current.y - this.control.y);
|
||||
return this.makeAbsolute(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
this.makeAbsolute = function(p) {
|
||||
|
@ -1146,7 +1241,6 @@ if(!window.console) {
|
|||
if (ctx != null) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
}
|
||||
}
|
||||
|
||||
else if (pp.command.toUpperCase() == 'A') {
|
||||
while (!pp.isCommandOrEnd()) {
|
||||
var curr = pp.current;
|
||||
|
@ -1304,7 +1398,7 @@ if(!window.console) {
|
|||
// definitions element
|
||||
svg.Element.defs = function(node) {
|
||||
this.base = svg.Element.ElementBase;
|
||||
this.base(node);
|
||||
this.base(node);
|
||||
|
||||
this.render = function(ctx) {
|
||||
// NOOP
|
||||
|
@ -1324,15 +1418,20 @@ if(!window.console) {
|
|||
var child = this.children[i];
|
||||
this.stops.push(child);
|
||||
}
|
||||
|
||||
|
||||
this.getGradient = function() {
|
||||
// OVERRIDE ME!
|
||||
}
|
||||
|
||||
this.createGradient = function(ctx, element) {
|
||||
var stopsContainer = this;
|
||||
if (this.attribute('xlink:href').hasValue()) {
|
||||
stopsContainer = this.attribute('xlink:href').Definition.getDefinition();
|
||||
}
|
||||
|
||||
var g = this.getGradient(ctx, element);
|
||||
for (var i=0; i<this.stops.length; i++) {
|
||||
g.addColorStop(this.stops[i].offset, this.stops[i].color);
|
||||
for (var i=0; i<stopsContainer.stops.length; i++) {
|
||||
g.addColorStop(stopsContainer.stops[i].offset, stopsContainer.stops[i].color);
|
||||
}
|
||||
return g;
|
||||
}
|
||||
|
@ -1360,7 +1459,15 @@ if(!window.console) {
|
|||
? bb.y() + bb.height() * this.attribute('y2').numValue()
|
||||
: this.attribute('y2').Length.toPixels('y'));
|
||||
|
||||
return ctx.createLinearGradient(x1, y1, x2, y2);
|
||||
var p1 = new svg.Point(x1, y1);
|
||||
var p2 = new svg.Point(x2, y2);
|
||||
if (this.attribute('gradientTransform').hasValue()) {
|
||||
var transform = new svg.Transform(this.attribute('gradientTransform').value);
|
||||
transform.applyToPoint(p1);
|
||||
transform.applyToPoint(p2);
|
||||
}
|
||||
|
||||
return ctx.createLinearGradient(p1.x, p1.y, p2.x, p2.y);
|
||||
}
|
||||
}
|
||||
svg.Element.linearGradient.prototype = new svg.Element.GradientBase;
|
||||
|
@ -1397,7 +1504,15 @@ if(!window.console) {
|
|||
? (bb.width() + bb.height()) / 2.0 * this.attribute('r').numValue()
|
||||
: this.attribute('r').Length.toPixels());
|
||||
|
||||
return ctx.createRadialGradient(fx, fy, 0, cx, cy, r);
|
||||
var c = new svg.Point(cx, cy);
|
||||
var f = new svg.Point(fx, fy);
|
||||
if (this.attribute('gradientTransform').hasValue()) {
|
||||
var transform = new svg.Transform(this.attribute('gradientTransform').value);
|
||||
transform.applyToPoint(c);
|
||||
transform.applyToPoint(f);
|
||||
}
|
||||
|
||||
return ctx.createRadialGradient(f.x, f.y, 0, c.x, c.y, r);
|
||||
}
|
||||
}
|
||||
svg.Element.radialGradient.prototype = new svg.Element.GradientBase;
|
||||
|
@ -1555,10 +1670,26 @@ if(!window.console) {
|
|||
var x = this.attribute('x').Length.toPixels('x');
|
||||
var y = this.attribute('y').Length.toPixels('y');
|
||||
for (var i=0; i<this.children.length; i++) {
|
||||
this.children[i].x = x;
|
||||
this.children[i].y = y;
|
||||
this.children[i].render(ctx);
|
||||
x += this.children[i].measureText(ctx);
|
||||
var child = this.children[i];
|
||||
|
||||
if (child.attribute('x').hasValue()) {
|
||||
child.x = child.attribute('x').Length.toPixels('x');
|
||||
}
|
||||
else {
|
||||
if (child.attribute('dx').hasValue()) x += child.attribute('dx').Length.toPixels('x');
|
||||
child.x = x;
|
||||
x += child.measureText(ctx);
|
||||
}
|
||||
|
||||
if (child.attribute('y').hasValue()) {
|
||||
child.y = child.attribute('y').Length.toPixels('y');
|
||||
}
|
||||
else {
|
||||
if (child.attribute('dy').hasValue()) y += child.attribute('dy').Length.toPixels('y');
|
||||
child.y = y;
|
||||
}
|
||||
|
||||
child.render(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1578,7 +1709,9 @@ if(!window.console) {
|
|||
}
|
||||
|
||||
this.measureText = function(ctx) {
|
||||
return ctx.measureText(svg.compressSpaces(this.getText())).width;
|
||||
var textToMeasure = svg.compressSpaces(this.getText());
|
||||
if (!ctx.measureText) return textToMeasure.length * 10;
|
||||
return ctx.measureText(textToMeasure).width;
|
||||
}
|
||||
}
|
||||
svg.Element.TextElementBase.prototype = new svg.Element.RenderedElementBase;
|
||||
|
@ -1608,6 +1741,85 @@ if(!window.console) {
|
|||
}
|
||||
svg.Element.tref.prototype = new svg.Element.TextElementBase;
|
||||
|
||||
// a element
|
||||
svg.Element.a = function(node) {
|
||||
this.base = svg.Element.TextElementBase;
|
||||
this.base(node);
|
||||
|
||||
this.hasText = true;
|
||||
for (var i=0; i<node.childNodes.length; i++) {
|
||||
if (node.childNodes[i].nodeType != 3) this.hasText = false;
|
||||
}
|
||||
|
||||
// this might contain text
|
||||
this.text = this.hasText ? node.childNodes[0].nodeValue : '';
|
||||
this.getText = function() {
|
||||
return this.text;
|
||||
}
|
||||
|
||||
this.baseRenderChildren = this.renderChildren;
|
||||
this.renderChildren = function(ctx) {
|
||||
if (this.hasText) {
|
||||
// render as text element
|
||||
this.baseRenderChildren(ctx);
|
||||
var fontSize = new svg.Property('fontSize', svg.Font.Parse(svg.ctx.font).fontSize);
|
||||
svg.Mouse.checkBoundingBox(this, new svg.BoundingBox(this.x, this.y - fontSize.Length.toPixels('y'), this.x + this.measureText(ctx), this.y));
|
||||
}
|
||||
else {
|
||||
// render as temporary group
|
||||
var g = new svg.Element.g();
|
||||
g.children = this.children;
|
||||
g.parent = this;
|
||||
g.render(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
this.onclick = function() {
|
||||
window.open(this.attribute('xlink:href').value);
|
||||
}
|
||||
|
||||
this.onmousemove = function() {
|
||||
svg.ctx.canvas.style.cursor = 'pointer';
|
||||
}
|
||||
}
|
||||
svg.Element.a.prototype = new svg.Element.TextElementBase;
|
||||
|
||||
// image element
|
||||
svg.Element.image = function(node) {
|
||||
this.base = svg.Element.RenderedElementBase;
|
||||
this.base(node);
|
||||
|
||||
svg.Images.push(this);
|
||||
this.img = document.createElement('img');
|
||||
this.loaded = false;
|
||||
var that = this;
|
||||
this.img.onload = function() { that.loaded = true; }
|
||||
this.img.src = this.attribute('xlink:href').value;
|
||||
|
||||
this.renderChildren = function(ctx) {
|
||||
var x = this.attribute('x').Length.toPixels('x');
|
||||
var y = this.attribute('y').Length.toPixels('y');
|
||||
|
||||
var width = this.attribute('width').Length.toPixels('x');
|
||||
var height = this.attribute('height').Length.toPixels('y');
|
||||
if (width == 0 || height == 0) return;
|
||||
|
||||
ctx.save();
|
||||
ctx.translate(x, y);
|
||||
svg.AspectRatio(ctx,
|
||||
this.attribute('preserveAspectRatio').value,
|
||||
width,
|
||||
this.img.width,
|
||||
height,
|
||||
this.img.height,
|
||||
0,
|
||||
0);
|
||||
ctx.drawImage(this.img, 0, 0);
|
||||
ctx.restore();
|
||||
}
|
||||
}
|
||||
svg.Element.image.prototype = new svg.Element.RenderedElementBase;
|
||||
|
||||
// group element
|
||||
svg.Element.g = function(node) {
|
||||
this.base = svg.Element.RenderedElementBase;
|
||||
|
@ -1621,14 +1833,7 @@ if(!window.console) {
|
|||
this.base(node);
|
||||
}
|
||||
svg.Element.symbol.prototype = new svg.Element.RenderedElementBase;
|
||||
|
||||
// a element
|
||||
svg.Element.a = function(node) {
|
||||
this.base = svg.Element.RenderedElementBase;
|
||||
this.base(node);
|
||||
}
|
||||
svg.Element.a.prototype = new svg.Element.RenderedElementBase;
|
||||
|
||||
|
||||
// style element
|
||||
svg.Element.style = function(node) {
|
||||
this.base = svg.Element.ElementBase;
|
||||
|
@ -1658,7 +1863,6 @@ if(!window.console) {
|
|||
svg.Styles[cssClass] = props;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1676,8 +1880,17 @@ if(!window.console) {
|
|||
if (this.attribute('y').hasValue()) ctx.translate(0, this.attribute('y').Length.toPixels('y'));
|
||||
}
|
||||
|
||||
this.getDefinition = function() {
|
||||
return this.attribute('xlink:href').Definition.getDefinition();
|
||||
}
|
||||
|
||||
this.path = function(ctx) {
|
||||
var element = this.getDefinition();
|
||||
if (element != null) element.path(ctx);
|
||||
}
|
||||
|
||||
this.renderChildren = function(ctx) {
|
||||
var element = this.attribute('xlink:href').Definition.getDefinition();
|
||||
var element = this.getDefinition();
|
||||
if (element != null) element.render(ctx);
|
||||
}
|
||||
}
|
||||
|
@ -1732,33 +1945,89 @@ if(!window.console) {
|
|||
// load from xml
|
||||
svg.loadXml = function(ctx, xml) {
|
||||
svg.init(ctx);
|
||||
|
||||
var mapXY = function(p) {
|
||||
var e = ctx.canvas;
|
||||
while (e) {
|
||||
p.x -= e.offsetLeft;
|
||||
p.y -= e.offsetTop;
|
||||
e = e.offsetParent;
|
||||
}
|
||||
if (window.scrollX) p.x += window.scrollX;
|
||||
if (window.scrollY) p.y += window.scrollY;
|
||||
return p;
|
||||
}
|
||||
|
||||
// bind mouse
|
||||
if (svg.opts == null || svg.opts['ignoreMouse'] != true) {
|
||||
ctx.canvas.onclick = function(e) {
|
||||
var p = mapXY(new svg.Point(e != null ? e.clientX : event.clientX, e != null ? e.clientY : event.clientY));
|
||||
svg.Mouse.onclick(p.x, p.y);
|
||||
};
|
||||
ctx.canvas.onmousemove = function(e) {
|
||||
var p = mapXY(new svg.Point(e != null ? e.clientX : event.clientX, e != null ? e.clientY : event.clientY));
|
||||
svg.Mouse.onmousemove(p.x, p.y);
|
||||
};
|
||||
}
|
||||
|
||||
var dom = svg.parseXml(xml);
|
||||
var e = svg.CreateElement(dom.documentElement);
|
||||
|
||||
// set canvas size
|
||||
if (e.attribute('width').hasValue()) {
|
||||
ctx.canvas.width = e.attribute('width').Length.toPixels(ctx.canvas.parentNode.clientWidth);
|
||||
}
|
||||
if (e.attribute('height').hasValue()) {
|
||||
ctx.canvas.height = e.attribute('height').Length.toPixels(ctx.canvas.parentNode.clientHeight);
|
||||
}
|
||||
svg.ViewPort.SetCurrent(ctx.canvas.clientWidth, ctx.canvas.clientHeight);
|
||||
|
||||
|
||||
// render loop
|
||||
ctx.clearRect(0, 0, ctx.canvas.clientWidth, ctx.canvas.clientHeight);
|
||||
e.render(ctx);
|
||||
var isFirstRender = true;
|
||||
var draw = function() {
|
||||
// set canvas size
|
||||
if (e.style('width').hasValue()) {
|
||||
ctx.canvas.width = e.style('width').Length.toPixels(ctx.canvas.parentNode.clientWidth);
|
||||
}
|
||||
if (e.style('height').hasValue()) {
|
||||
ctx.canvas.height = e.style('height').Length.toPixels(ctx.canvas.parentNode.clientHeight);
|
||||
}
|
||||
svg.ViewPort.SetCurrent(ctx.canvas.clientWidth, ctx.canvas.clientHeight);
|
||||
|
||||
// clear and render
|
||||
ctx.clearRect(0, 0, ctx.canvas.clientWidth, ctx.canvas.clientHeight);
|
||||
e.render(ctx);
|
||||
if (isFirstRender) {
|
||||
isFirstRender = false;
|
||||
if (svg.opts != null && typeof(svg.opts['renderCallback']) == 'function') svg.opts['renderCallback']();
|
||||
}
|
||||
}
|
||||
|
||||
var waitingForImages = true;
|
||||
if (svg.ImagesLoaded()) {
|
||||
waitingForImages = false;
|
||||
draw();
|
||||
}
|
||||
svg.intervalID = setInterval(function() {
|
||||
// update animations
|
||||
var needUpdate = false;
|
||||
for (var i=0; i<svg.Animations.length; i++) {
|
||||
needUpdate = needUpdate | svg.Animations[i].update(1000 / svg.FRAMERATE);
|
||||
|
||||
if (waitingForImages && svg.ImagesLoaded()) {
|
||||
waitingForImages = false;
|
||||
needUpdate = true;
|
||||
}
|
||||
|
||||
// need update from mouse events?
|
||||
if (svg.opts == null || svg.opts['ignoreMouse'] != true) {
|
||||
needUpdate = needUpdate | svg.Mouse.hasEvents();
|
||||
}
|
||||
|
||||
// need update from animations?
|
||||
if (svg.opts == null || svg.opts['ignoreAnimation'] != true) {
|
||||
for (var i=0; i<svg.Animations.length; i++) {
|
||||
needUpdate = needUpdate | svg.Animations[i].update(1000 / svg.FRAMERATE);
|
||||
}
|
||||
}
|
||||
|
||||
// need update from redraw?
|
||||
if (svg.opts != null && typeof(svg.opts['forceRedraw']) == 'function') {
|
||||
if (svg.opts['forceRedraw']() == true) needUpdate = true;
|
||||
}
|
||||
|
||||
// render if needed
|
||||
if (needUpdate) {
|
||||
ctx.clearRect(0, 0, ctx.canvas.clientWidth, ctx.canvas.clientHeight);
|
||||
e.render(ctx);
|
||||
draw();
|
||||
svg.Mouse.runEvents(); // run and clear our events
|
||||
}
|
||||
}, 1000 / svg.FRAMERATE);
|
||||
}
|
||||
|
@ -1769,6 +2038,56 @@ if(!window.console) {
|
|||
}
|
||||
}
|
||||
|
||||
svg.Mouse = new (function() {
|
||||
this.events = [];
|
||||
this.hasEvents = function() { return this.events.length != 0; }
|
||||
|
||||
this.onclick = function(x, y) {
|
||||
this.events.push({ type: 'onclick', x: x, y: y,
|
||||
run: function(e) { if (e.onclick) e.onclick(); }
|
||||
});
|
||||
}
|
||||
|
||||
this.onmousemove = function(x, y) {
|
||||
this.events.push({ type: 'onmousemove', x: x, y: y,
|
||||
run: function(e) { if (e.onmousemove) e.onmousemove(); }
|
||||
});
|
||||
}
|
||||
|
||||
this.eventElements = [];
|
||||
|
||||
this.checkPath = function(element, ctx) {
|
||||
for (var i=0; i<this.events.length; i++) {
|
||||
var e = this.events[i];
|
||||
if (ctx.isPointInPath && ctx.isPointInPath(e.x, e.y)) this.eventElements[i] = element;
|
||||
}
|
||||
}
|
||||
|
||||
this.checkBoundingBox = function(element, bb) {
|
||||
for (var i=0; i<this.events.length; i++) {
|
||||
var e = this.events[i];
|
||||
if (bb.isPointInBox(e.x, e.y)) this.eventElements[i] = element;
|
||||
}
|
||||
}
|
||||
|
||||
this.runEvents = function() {
|
||||
svg.ctx.canvas.style.cursor = '';
|
||||
|
||||
for (var i=0; i<this.events.length; i++) {
|
||||
var e = this.events[i];
|
||||
var element = this.eventElements[i];
|
||||
while (element) {
|
||||
e.run(element);
|
||||
element = element.parent;
|
||||
}
|
||||
}
|
||||
|
||||
// done running, clear
|
||||
this.events = [];
|
||||
this.eventElements = [];
|
||||
}
|
||||
});
|
||||
|
||||
return svg;
|
||||
}
|
||||
})();
|
||||
})();
|
198
public/svg-edit/editor/contextmenu/jquery.contextMenu.js
Executable file
198
public/svg-edit/editor/contextmenu/jquery.contextMenu.js
Executable file
|
@ -0,0 +1,198 @@
|
|||
// jQuery Context Menu Plugin
|
||||
//
|
||||
// Version 1.01
|
||||
//
|
||||
// Cory S.N. LaViska
|
||||
// A Beautiful Site (http://abeautifulsite.net/)
|
||||
// Modified by Alexis Deveria
|
||||
//
|
||||
// More info: http://abeautifulsite.net/2008/09/jquery-context-menu-plugin/
|
||||
//
|
||||
// Terms of Use
|
||||
//
|
||||
// This plugin is dual-licensed under the GNU General Public License
|
||||
// and the MIT License and is copyright A Beautiful Site, LLC.
|
||||
//
|
||||
if(jQuery)( function() {
|
||||
$.extend($.fn, {
|
||||
|
||||
contextMenu: function(o, callback) {
|
||||
// Defaults
|
||||
if( o.menu == undefined ) return false;
|
||||
if( o.inSpeed == undefined ) o.inSpeed = 150;
|
||||
if( o.outSpeed == undefined ) o.outSpeed = 75;
|
||||
// 0 needs to be -1 for expected results (no fade)
|
||||
if( o.inSpeed == 0 ) o.inSpeed = -1;
|
||||
if( o.outSpeed == 0 ) o.outSpeed = -1;
|
||||
// Loop each context menu
|
||||
$(this).each( function() {
|
||||
var el = $(this);
|
||||
var offset = $(el).offset();
|
||||
// Add contextMenu class
|
||||
$('#' + o.menu).addClass('contextMenu');
|
||||
// Simulate a true right click
|
||||
$(this).mousedown( function(e) {
|
||||
var evt = e;
|
||||
$(this).mouseup( function(e) {
|
||||
var srcElement = $(this);
|
||||
$(this).unbind('mouseup');
|
||||
if( evt.button == 2 || o.allowLeft) {
|
||||
e.stopPropagation();
|
||||
// Hide context menus that may be showing
|
||||
$(".contextMenu").hide();
|
||||
// Get this context menu
|
||||
var menu = $('#' + o.menu);
|
||||
|
||||
if( $(el).hasClass('disabled') ) return false;
|
||||
|
||||
// Detect mouse position
|
||||
var d = {}, x = e.pageX, y = e.pageY;
|
||||
|
||||
var x_off = $(window).width() - menu.width(),
|
||||
y_off = $(window).height() - menu.height();
|
||||
|
||||
if(x > x_off) x = x_off-15;
|
||||
if(y > y_off) y = y_off-15;
|
||||
|
||||
// Show the menu
|
||||
$(document).unbind('click');
|
||||
$(menu).css({ top: y, left: x }).fadeIn(o.inSpeed);
|
||||
// Hover events
|
||||
$(menu).find('A').mouseover( function() {
|
||||
$(menu).find('LI.hover').removeClass('hover');
|
||||
$(this).parent().addClass('hover');
|
||||
}).mouseout( function() {
|
||||
$(menu).find('LI.hover').removeClass('hover');
|
||||
});
|
||||
|
||||
// Keyboard
|
||||
$(document).keypress( function(e) {
|
||||
switch( e.keyCode ) {
|
||||
case 38: // up
|
||||
if( $(menu).find('LI.hover').size() == 0 ) {
|
||||
$(menu).find('LI:last').addClass('hover');
|
||||
} else {
|
||||
$(menu).find('LI.hover').removeClass('hover').prevAll('LI:not(.disabled)').eq(0).addClass('hover');
|
||||
if( $(menu).find('LI.hover').size() == 0 ) $(menu).find('LI:last').addClass('hover');
|
||||
}
|
||||
break;
|
||||
case 40: // down
|
||||
if( $(menu).find('LI.hover').size() == 0 ) {
|
||||
$(menu).find('LI:first').addClass('hover');
|
||||
} else {
|
||||
$(menu).find('LI.hover').removeClass('hover').nextAll('LI:not(.disabled)').eq(0).addClass('hover');
|
||||
if( $(menu).find('LI.hover').size() == 0 ) $(menu).find('LI:first').addClass('hover');
|
||||
}
|
||||
break;
|
||||
case 13: // enter
|
||||
$(menu).find('LI.hover A').trigger('click');
|
||||
break;
|
||||
case 27: // esc
|
||||
$(document).trigger('click');
|
||||
break
|
||||
}
|
||||
});
|
||||
|
||||
// When items are selected
|
||||
$('#' + o.menu).find('A').unbind('mouseup');
|
||||
$('#' + o.menu).find('LI:not(.disabled) A').mouseup( function() {
|
||||
$(document).unbind('click').unbind('keypress');
|
||||
$(".contextMenu").hide();
|
||||
// Callback
|
||||
if( callback ) callback( $(this).attr('href').substr(1), $(srcElement), {x: x - offset.left, y: y - offset.top, docX: x, docY: y} );
|
||||
return false;
|
||||
});
|
||||
|
||||
// Hide bindings
|
||||
setTimeout( function() { // Delay for Mozilla
|
||||
$(document).click( function() {
|
||||
$(document).unbind('click').unbind('keypress');
|
||||
$(menu).fadeOut(o.outSpeed);
|
||||
return false;
|
||||
});
|
||||
}, 0);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Disable text selection
|
||||
if( $.browser.mozilla ) {
|
||||
$('#' + o.menu).each( function() { $(this).css({ 'MozUserSelect' : 'none' }); });
|
||||
} else if( $.browser.msie ) {
|
||||
$('#' + o.menu).each( function() { $(this).bind('selectstart.disableTextSelect', function() { return false; }); });
|
||||
} else {
|
||||
$('#' + o.menu).each(function() { $(this).bind('mousedown.disableTextSelect', function() { return false; }); });
|
||||
}
|
||||
// Disable browser context menu (requires both selectors to work in IE/Safari + FF/Chrome)
|
||||
$(el).add($('UL.contextMenu')).bind('contextmenu', function() { return false; });
|
||||
|
||||
});
|
||||
return $(this);
|
||||
},
|
||||
|
||||
// Disable context menu items on the fly
|
||||
disableContextMenuItems: function(o) {
|
||||
if( o == undefined ) {
|
||||
// Disable all
|
||||
$(this).find('LI').addClass('disabled');
|
||||
return( $(this) );
|
||||
}
|
||||
$(this).each( function() {
|
||||
if( o != undefined ) {
|
||||
var d = o.split(',');
|
||||
for( var i = 0; i < d.length; i++ ) {
|
||||
$(this).find('A[href="' + d[i] + '"]').parent().addClass('disabled');
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
return( $(this) );
|
||||
},
|
||||
|
||||
// Enable context menu items on the fly
|
||||
enableContextMenuItems: function(o) {
|
||||
if( o == undefined ) {
|
||||
// Enable all
|
||||
$(this).find('LI.disabled').removeClass('disabled');
|
||||
return( $(this) );
|
||||
}
|
||||
$(this).each( function() {
|
||||
if( o != undefined ) {
|
||||
var d = o.split(',');
|
||||
for( var i = 0; i < d.length; i++ ) {
|
||||
$(this).find('A[href="' + d[i] + '"]').parent().removeClass('disabled');
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
return( $(this) );
|
||||
},
|
||||
|
||||
// Disable context menu(s)
|
||||
disableContextMenu: function() {
|
||||
$(this).each( function() {
|
||||
$(this).addClass('disabled');
|
||||
});
|
||||
return( $(this) );
|
||||
},
|
||||
|
||||
// Enable context menu(s)
|
||||
enableContextMenu: function() {
|
||||
$(this).each( function() {
|
||||
$(this).removeClass('disabled');
|
||||
});
|
||||
return( $(this) );
|
||||
},
|
||||
|
||||
// Destroy context menu(s)
|
||||
destroyContextMenu: function() {
|
||||
// Destroy specified context menus
|
||||
$(this).each( function() {
|
||||
// Disable action
|
||||
$(this).unbind('mousedown').unbind('mouseup');
|
||||
});
|
||||
return( $(this) );
|
||||
}
|
||||
|
||||
});
|
||||
})(jQuery);
|
22
public/svg-edit/editor/contextmenu/jquery.contextMenu.min.js
vendored
Normal file
22
public/svg-edit/editor/contextmenu/jquery.contextMenu.min.js
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
// jQuery Context Menu Plugin
|
||||
//
|
||||
// Version 1.01
|
||||
//
|
||||
// Cory S.N. LaViska
|
||||
// A Beautiful Site (http://abeautifulsite.net/)
|
||||
//
|
||||
// More info: http://abeautifulsite.net/2008/09/jquery-context-menu-plugin/
|
||||
//
|
||||
// Terms of Use
|
||||
//
|
||||
// This plugin is dual-licensed under the GNU General Public License
|
||||
// and the MIT License and is copyright A Beautiful Site, LLC.
|
||||
//
|
||||
jQuery&&function(){$.extend($.fn,{contextMenu:function(a,e){if(a.menu==undefined)return false;if(a.inSpeed==undefined)a.inSpeed=150;if(a.outSpeed==undefined)a.outSpeed=75;if(a.inSpeed==0)a.inSpeed=-1;if(a.outSpeed==0)a.outSpeed=-1;$(this).each(function(){var d=$(this),i=$(d).offset();$("#"+a.menu).addClass("contextMenu");$(this).mousedown(function(j){j.stopPropagation();$(this).mouseup(function(f){f.stopPropagation();var k=$(this);$(this).unbind("mouseup");if(j.button==2){$(".contextMenu").hide();
|
||||
var b=$("#"+a.menu);if($(d).hasClass("disabled"))return false;var c={},g,h;if(self.innerHeight){c.pageYOffset=self.pageYOffset;c.pageXOffset=self.pageXOffset;c.innerHeight=self.innerHeight;c.innerWidth=self.innerWidth}else if(document.documentElement&&document.documentElement.clientHeight){c.pageYOffset=document.documentElement.scrollTop;c.pageXOffset=document.documentElement.scrollLeft;c.innerHeight=document.documentElement.clientHeight;c.innerWidth=document.documentElement.clientWidth}else if(document.body){c.pageYOffset=
|
||||
document.body.scrollTop;c.pageXOffset=document.body.scrollLeft;c.innerHeight=document.body.clientHeight;c.innerWidth=document.body.clientWidth}f.pageX?g=f.pageX:g=f.clientX+c.scrollLeft;f.pageY?h=f.pageY:h=f.clientY+c.scrollTop;$(document).unbind("click");$(b).css({top:h,left:g}).fadeIn(a.inSpeed);$(b).find("A").mouseover(function(){$(b).find("LI.hover").removeClass("hover");$(this).parent().addClass("hover")}).mouseout(function(){$(b).find("LI.hover").removeClass("hover")});$(document).keypress(function(l){switch(l.keyCode){case 38:if($(b).find("LI.hover").size()==
|
||||
0)$(b).find("LI:last").addClass("hover");else{$(b).find("LI.hover").removeClass("hover").prevAll("LI:not(.disabled)").eq(0).addClass("hover");$(b).find("LI.hover").size()==0&&$(b).find("LI:last").addClass("hover")}break;case 40:if($(b).find("LI.hover").size()==0)$(b).find("LI:first").addClass("hover");else{$(b).find("LI.hover").removeClass("hover").nextAll("LI:not(.disabled)").eq(0).addClass("hover");$(b).find("LI.hover").size()==0&&$(b).find("LI:first").addClass("hover")}break;case 13:$(b).find("LI.hover A").trigger("click");
|
||||
break;case 27:$(document).trigger("click");break}});$("#"+a.menu).find("A").unbind("click");$("#"+a.menu).find("LI:not(.disabled) A").click(function(){$(document).unbind("click").unbind("keypress");$(".contextMenu").hide();e&&e($(this).attr("href").substr(1),$(k),{x:g-i.left,y:h-i.top,docX:g,docY:h});return false});setTimeout(function(){$(document).click(function(){$(document).unbind("click").unbind("keypress");$(b).fadeOut(a.outSpeed);return false})},0)}})});if($.browser.mozilla)$("#"+a.menu).each(function(){$(this).css({MozUserSelect:"none"})});
|
||||
else $.browser.msie?$("#"+a.menu).each(function(){$(this).bind("selectstart.disableTextSelect",function(){return false})}):$("#"+a.menu).each(function(){$(this).bind("mousedown.disableTextSelect",function(){return false})});$(d).add($("UL.contextMenu")).bind("contextmenu",function(){return false})});return $(this)},disableContextMenuItems:function(a){if(a==undefined){$(this).find("LI").addClass("disabled");return $(this)}$(this).each(function(){if(a!=undefined)for(var e=a.split(","),d=0;d<e.length;d++)$(this).find('A[href="'+
|
||||
e[d]+'"]').parent().addClass("disabled")});return $(this)},enableContextMenuItems:function(a){if(a==undefined){$(this).find("LI.disabled").removeClass("disabled");return $(this)}$(this).each(function(){if(a!=undefined)for(var e=a.split(","),d=0;d<e.length;d++)$(this).find('A[href="'+e[d]+'"]').parent().removeClass("disabled")});return $(this)},disableContextMenu:function(){$(this).each(function(){$(this).addClass("disabled")});return $(this)},enableContextMenu:function(){$(this).each(function(){$(this).removeClass("disabled")});
|
||||
return $(this)},destroyContextMenu:function(){$(this).each(function(){$(this).unbind("mousedown").unbind("mouseup")});return $(this)}})}(jQuery);
|
|
@ -256,8 +256,9 @@ svgEditor.addExtension("Connector", function(S) {
|
|||
|
||||
svgCanvas.moveSelectedElements = function() {
|
||||
svgCanvas.removeFromSelection($(conn_sel).toArray());
|
||||
mse.apply(this, arguments);
|
||||
var cmd = mse.apply(this, arguments);
|
||||
updateConnectors();
|
||||
return cmd;
|
||||
}
|
||||
|
||||
se_ns = svgCanvas.getEditorNS();
|
||||
|
@ -486,6 +487,12 @@ svgEditor.addExtension("Connector", function(S) {
|
|||
}
|
||||
},
|
||||
selectedChanged: function(opts) {
|
||||
// TODO: Find better way to skip operations if no connectors are in use
|
||||
if(!$(svgcontent).find(conn_sel).length) return;
|
||||
|
||||
if(svgCanvas.getMode() == 'connector') {
|
||||
svgCanvas.setMode('select');
|
||||
}
|
||||
|
||||
// Use this to update the current selected elements
|
||||
selElems = opts.elems;
|
||||
|
|
150
public/svg-edit/editor/extensions/ext-grid.js
Normal file
150
public/svg-edit/editor/extensions/ext-grid.js
Normal file
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* ext-grid.js
|
||||
*
|
||||
* Licensed under the Apache License, Version 2
|
||||
*
|
||||
* Copyright(c) 2010 Redou Mine
|
||||
*
|
||||
*/
|
||||
|
||||
svgEditor.addExtension("view_grid", function(s) {
|
||||
/*
|
||||
* Config for grid-lines
|
||||
*/
|
||||
var gridConfig = {
|
||||
'1x1': { height: 1, width: 1, color: '#CCC', strokeWidth: 0.05, opacity: 1 },
|
||||
'5x5': { height: 5, width: 5, color: '#BBB', strokeWidth: 0.2, opacity: 1 },
|
||||
'10x10': { height: 10, width: 10, color: '#AAA', strokeWidth: 0.2, opacity: 1 },
|
||||
'100x100': { height: 100, width: 100, color: '#888', strokeWidth: 0.2, opacity: 1 }
|
||||
};
|
||||
|
||||
var svgdoc = document.getElementById("svgcanvas").ownerDocument,
|
||||
svgns = "http://www.w3.org/2000/svg",
|
||||
dims = svgEditor.curConfig.dimensions,
|
||||
svgroot = s.svgroot;
|
||||
|
||||
/*
|
||||
* copied from svgcanvas.js line 1138-1157 (version: 2.5 rc1)
|
||||
*/
|
||||
var assignAttributes = function(node, attrs, suspendLength, unitCheck) {
|
||||
if (!suspendLength) suspendLength = 0;
|
||||
// Opera has a problem with suspendRedraw() apparently
|
||||
var handle = null;
|
||||
if (!window.opera) svgroot.suspendRedraw(suspendLength);
|
||||
|
||||
for (var i in attrs) {
|
||||
var ns = (i.substr(0, 4) == "xml:" ? xmlns :
|
||||
i.substr(0, 6) == "xlink:" ? xlinkns : null);
|
||||
|
||||
if (ns || !unitCheck) {
|
||||
node.setAttributeNS(ns, i, attrs[i]);
|
||||
} else {
|
||||
setUnitAttr(node, i, attrs[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!window.opera) svgroot.unsuspendRedraw(handle);
|
||||
};
|
||||
|
||||
|
||||
// create svg for grid
|
||||
var canvasgrid = svgdoc.createElementNS(svgns, "svg");
|
||||
assignAttributes(canvasgrid, {
|
||||
'id': 'canvasGrid',
|
||||
'width': '100%',
|
||||
'height': '100%',
|
||||
'x': 0,
|
||||
'y': 0,
|
||||
'overflow': 'visible',
|
||||
'viewBox': '0 0 ' + dims[0] + ' ' + dims[1],
|
||||
'display': 'none'
|
||||
});
|
||||
$('#canvasBackground').append(canvasgrid);
|
||||
|
||||
// create each grid
|
||||
$.each(gridConfig, function(key, value) {
|
||||
// grid-pattern
|
||||
var gridPattern = svgdoc.createElementNS(svgns, "pattern");
|
||||
assignAttributes(gridPattern, {
|
||||
'id': 'gridpattern' + key,
|
||||
'patternUnits': 'userSpaceOnUse',
|
||||
'x': -(value.strokeWidth / 2), // position for strokewidth
|
||||
'y': -(value.strokeWidth / 2), // position for strokewidth
|
||||
'width': value.width,
|
||||
'height': value.height
|
||||
});
|
||||
var gridPattern_hoLine = svgdoc.createElementNS(svgns, "line");
|
||||
assignAttributes(gridPattern_hoLine, {
|
||||
'fill': 'none',
|
||||
'stroke-width': value.strokeWidth,
|
||||
'x1': 0,
|
||||
'y1': 0,
|
||||
'x2': value.width,
|
||||
'y2': 0,
|
||||
'stroke': value.color
|
||||
});
|
||||
var gridPattern_veLine = svgdoc.createElementNS(svgns, "line");
|
||||
assignAttributes(gridPattern_veLine, {
|
||||
'fill': 'none',
|
||||
'stroke-width': value.strokeWidth,
|
||||
'x1': 0,
|
||||
'y1': 0,
|
||||
'x2': 0,
|
||||
'y2': value.height,
|
||||
'stroke': value.color
|
||||
});
|
||||
|
||||
gridPattern.appendChild(gridPattern_hoLine);
|
||||
gridPattern.appendChild(gridPattern_veLine);
|
||||
$('#svgroot defs').append(gridPattern);
|
||||
|
||||
// grid-box
|
||||
var gridBox = svgdoc.createElementNS(svgns, "rect");
|
||||
assignAttributes(gridBox, {
|
||||
'width': '100%',
|
||||
'height': '100%',
|
||||
'x': 0,
|
||||
'y': 0,
|
||||
'stroke-width': 0,
|
||||
'stroke': 'none',
|
||||
'fill': 'url(#gridpattern' + key + ')',
|
||||
'opacity': value.opacity,
|
||||
'style': 'pointer-events: none; display:visible;'
|
||||
});
|
||||
$('#canvasGrid').append(gridBox);
|
||||
});
|
||||
|
||||
return {
|
||||
name: "view_grid",
|
||||
svgicons: "extensions/grid-icon.xml",
|
||||
|
||||
zoomChanged: function(zoomlevel) {
|
||||
// update size
|
||||
var viewBox = "0 0 " + svgCanvas.contentW + " " + svgCanvas.contentH;
|
||||
$('#canvasGrid').attr("viewBox", viewBox);
|
||||
},
|
||||
|
||||
buttons: [{
|
||||
id: "view_grid",
|
||||
type: "context",
|
||||
panel: "editor_panel",
|
||||
title: "Show/Hide Grid [G]",
|
||||
events: {
|
||||
'click': function() {
|
||||
var gr = !$('#view_grid').hasClass('push_button_pressed');
|
||||
if (gr) {
|
||||
svgEditor.curConfig.gridSnapping = true;
|
||||
$('#view_grid').addClass('push_button_pressed').removeClass('tool_button');
|
||||
$('#canvasGrid').attr('display', 'normal');
|
||||
}
|
||||
else {
|
||||
svgEditor.curConfig.gridSnapping = false;
|
||||
$('#view_grid').removeClass('push_button_pressed').addClass('tool_button');
|
||||
$('#canvasGrid').attr('display', 'none');
|
||||
}
|
||||
}
|
||||
}
|
||||
}]
|
||||
};
|
||||
});
|
|
@ -17,7 +17,7 @@ svgEditor.addExtension("imagelib", function() {
|
|||
{
|
||||
name: 'IAN Symbol Libraries',
|
||||
url: 'http://ian.umces.edu/symbols/catalog/svgedit/album_chooser.php',
|
||||
description: 'Free library of 2300+ illustrations'
|
||||
description: 'Free library of illustrations'
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -90,7 +90,7 @@ svgEditor.addExtension("imagelib", function() {
|
|||
function showBrowser() {
|
||||
var browser = $('#imgbrowse');
|
||||
if(!browser.length) {
|
||||
$('<div id=imgbrowse_holder><div id=imgbrowse>\
|
||||
$('<div id=imgbrowse_holder><div id=imgbrowse class=toolbar_button>\
|
||||
</div></div>').insertAfter('#svg_docprops');
|
||||
browser = $('#imgbrowse');
|
||||
|
||||
|
@ -101,24 +101,27 @@ svgEditor.addExtension("imagelib", function() {
|
|||
|
||||
var header = $('<h1>').prependTo(browser).text(all_libs);
|
||||
|
||||
var cancel = $('<input type=button value=Cancel>').appendTo(browser).click(function() {
|
||||
var cancel = $('<button>Cancel</button>').appendTo(browser).click(function() {
|
||||
$('#imgbrowse_holder').hide();
|
||||
}).css({
|
||||
position: 'absolute',
|
||||
top: 5,
|
||||
right: 5
|
||||
right: -10
|
||||
});
|
||||
|
||||
var back = $('<input type=button value="Show libraries">').appendTo(browser).click(function() {
|
||||
var back = $('<button>Show libraries</button>').appendTo(browser).click(function() {
|
||||
frame.attr('src', 'about:blank').hide();
|
||||
lib_opts.show();
|
||||
header.text(all_libs);
|
||||
}).css({
|
||||
position: 'absolute',
|
||||
top: 5,
|
||||
left: 5
|
||||
left: 10
|
||||
});
|
||||
|
||||
cancel.prepend($.getSvgIcon('cancel', true));
|
||||
back.prepend($.getSvgIcon('tool_imagelib', true));
|
||||
|
||||
$.each(img_libs, function(i, opts) {
|
||||
$('<li>').appendTo(lib_opts).text(opts.name).click(function() {
|
||||
frame.attr('src', opts.url).show();
|
||||
|
@ -175,7 +178,7 @@ svgEditor.addExtension("imagelib", function() {
|
|||
#imgbrowse > div,\
|
||||
#imgbrowse > ul {\
|
||||
position: absolute;\
|
||||
top: 36px;\
|
||||
top: 45px;\
|
||||
left: 10px;\
|
||||
right: 10px;\
|
||||
bottom: 10px;\
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="tool_imagelib">
|
||||
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300">
|
||||
<path fill="#c0c0c0" stroke-linejoin="round" stroke-width="14" stroke="#202020" fill-rule="nonzero" d="m70,194.72501l0,0c0,-10.30901 35.8172,-18.666 80,-18.666c44.18298,0 80,8.35699 80,18.666l0,74.66699c0,10.30899 -35.81702,18.66699 -80,18.66699c-44.1828,0 -80,-8.358 -80,-18.66699l0,-74.66699z"/>
|
||||
<path fill="#c0c0c0" stroke-linejoin="round" stroke-width="14" stroke="#202020" fill-rule="nonzero" d="m70,114.608l0,0c0,-10.309 35.8172,-18.6668 80,-18.6668c44.18298,0 80,8.3578 80,18.6668l0,74.66699c0,10.30901 -35.81702,18.666 -80,18.666c-44.1828,0 -80,-8.35699 -80,-18.666l0,-74.66699z"/>
|
||||
<path fill="#c0c0c0" stroke-linejoin="round" stroke-width="14" stroke="#202020" fill-rule="nonzero" d="m70,33.6667l0,0c0,-10.3094 35.8172,-18.6667 80,-18.6667c44.18298,0 80,8.3573 80,18.6667l0,74.6663c0,10.31 -35.81702,18.667 -80,18.667c-44.1828,0 -80,-8.357 -80,-18.667l0,-74.6663z"/>
|
||||
<path id="svg_1" fill="#c0c0c0" stroke-linejoin="round" stroke-width="14" stroke="#202020" fill-rule="nonzero" d="m230,32.33334c0,10.30931 -35.81726,18.66666 -80,18.66666c-44.1828,0 -80,-8.35735 -80,-18.66666"/>
|
||||
</svg>
|
||||
<svg width="201" height="211" xmlns="http://www.w3.org/2000/svg">
|
||||
<g>
|
||||
<path fill="#efe8b8" stroke="#d6c47c" stroke-linecap="round" d="m2.75,49.51761l56.56,-46.26761c12.73,8.25 25.71001,7 46.44,0.75l-56.03999,47.23944l-22.72002,25.01056l-24.23999,-26.73239z" id="svg_2" stroke-width="7"/>
|
||||
<path fill="#a03333" stroke="#3f3f3f" d="m3.75,203.25002c14.33301,7 30.66699,7 46,0l0,-152.00002c-14.66699,8 -32.33301,8 -47,0l1,152.00002zm45.75,-152.25002l56.25,-46.75l0,151l-56,48.00002m-47.25,-154.25002l57.25,-46.5" id="svg_1" stroke-width="7" stroke-linecap="round"/>
|
||||
<path fill="#efe8b8" stroke="#d6c47c" stroke-linecap="round" d="m49.75,49.51801l56.56,-46.26801c12.72998,8.25 25.71002,7 46.44,0.75l-56.03998,47.239l-22.72003,25.011l-24.23999,-26.73199z" stroke-width="7" id="svg_5"/>
|
||||
<path fill="#2f8e2f" stroke="#3f3f3f" d="m50.75,202.25c14.33301,7 30.66699,7.04253 46,0.04253l0,-151.04253c-14.66699,8 -32.33301,8 -47,0l1,151zm45.75,-151.25l56.25,-46.75l0,144.01219l-56,51.98782m-47.25,-151.25002l57.25,-46.5" stroke-width="7" stroke-linecap="round" id="svg_6"/>
|
||||
<path fill="#efe8b8" stroke="#d6c47c" stroke-linecap="round" d="m95.75,49.51801l56.56,-46.26801c12.72998,8.25 25.71002,7 46.44,0.75l-56.03998,47.239l-22.72003,25.011l-24.23999,-26.73199z" stroke-width="7" id="svg_10"/>
|
||||
<path fill="#336393" stroke="#3f3f3f" d="m96.75,200.29445c14.33301,7 30.66699,7 46,0l0,-149.04445c-14.66699,8 -32.33301,8 -47,0l1,149.04445zm45.75,-149.29445l56.25,-46.75l0,148.04445l-56,48m-47.25,-151.29445l57.25,-46.5" stroke-width="7" stroke-linecap="round" id="svg_11"/>
|
||||
</g>
|
||||
</svg>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.6 KiB |
|
@ -18,7 +18,7 @@ svgEditor.addExtension("server_opensave", {
|
|||
|
||||
svgEditor.setCustomHandlers({
|
||||
save: function(win, data) {
|
||||
var svg = "<?xml version='1.0'?>\n" + data;
|
||||
var svg = "<?xml version=\"1.0\"?>\n" + data;
|
||||
|
||||
var title = svgCanvas.getDocumentTitle();
|
||||
var filename = title.replace(/[^a-z0-9\.\_\-]+/gi, '_');
|
||||
|
@ -42,33 +42,34 @@ svgEditor.addExtension("server_opensave", {
|
|||
|
||||
c.width = svgCanvas.contentW;
|
||||
c.height = svgCanvas.contentH;
|
||||
canvg(c, data.svg);
|
||||
var datauri = c.toDataURL('image/png');
|
||||
|
||||
var uiStrings = svgEditor.uiStrings;
|
||||
var note = '';
|
||||
|
||||
// Check if there's issues
|
||||
if(issues.length) {
|
||||
var pre = "\n \u2022 ";
|
||||
note += ("\n\n" + pre + issues.join(pre));
|
||||
}
|
||||
|
||||
if(note.length) {
|
||||
alert(note);
|
||||
}
|
||||
|
||||
var title = svgCanvas.getDocumentTitle();
|
||||
var filename = title.replace(/[^a-z0-9\.\_\-]+/gi, '_');
|
||||
|
||||
var form = $('<form>').attr({
|
||||
method: 'post',
|
||||
action: save_png_action,
|
||||
target: 'output_frame'
|
||||
}) .append('<input type="hidden" name="output_png" value="' + datauri + '">')
|
||||
.append('<input type="hidden" name="filename" value="' + filename + '">')
|
||||
.appendTo('body')
|
||||
.submit().remove();
|
||||
canvg(c, data.svg, {renderCallback: function() {
|
||||
var datauri = c.toDataURL('image/png');
|
||||
|
||||
var uiStrings = svgEditor.uiStrings;
|
||||
var note = '';
|
||||
|
||||
// Check if there's issues
|
||||
if(issues.length) {
|
||||
var pre = "\n \u2022 ";
|
||||
note += ("\n\n" + pre + issues.join(pre));
|
||||
}
|
||||
|
||||
if(note.length) {
|
||||
alert(note);
|
||||
}
|
||||
|
||||
var title = svgCanvas.getDocumentTitle();
|
||||
var filename = title.replace(/[^a-z0-9\.\_\-]+/gi, '_');
|
||||
|
||||
var form = $('<form>').attr({
|
||||
method: 'post',
|
||||
action: save_png_action,
|
||||
target: 'output_frame'
|
||||
}) .append('<input type="hidden" name="output_png" value="' + datauri + '">')
|
||||
.append('<input type="hidden" name="filename" value="' + filename + '">')
|
||||
.appendTo('body')
|
||||
.submit().remove();
|
||||
}});
|
||||
|
||||
|
||||
}
|
||||
|
|
30
public/svg-edit/editor/extensions/grid-icon.xml
Normal file
30
public/svg-edit/editor/extensions/grid-icon.xml
Normal file
|
@ -0,0 +1,30 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<!--
|
||||
Sample icons file. This file looks like an SVG file with groups as its
|
||||
children. Each group element has an ID that must match the ID of the button given
|
||||
in the extension. The SVG inside the group makes up the actual icon, and
|
||||
needs use a viewBox instead of width/height for it to scale properly.
|
||||
|
||||
Multiple icons can be included, each within their own group.
|
||||
-->
|
||||
<g id="view_grid">
|
||||
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<g>
|
||||
<rect fill="#ffffff" stroke="#848484" x="2" y="2" width="20" height="20"/>
|
||||
<line fill="none" stroke="#848484" x1="11.84375" y1="-1.53125" x2="11.84375" y2="18.46875" transform="rotate(90, 11.8429, 8.46955)"/>
|
||||
<line fill="none" stroke="#848484" x1="11.90625" y1="5.21875" x2="11.90625" y2="25.21875" transform="rotate(90, 11.9054, 15.2196)"/>
|
||||
<line fill="none" stroke="#848484" x1="8.5" y1="2.03125" x2="8.5" y2="22.03125"/>
|
||||
<line fill="none" stroke="#848484" x1="15.5" y1="2.03125" x2="15.5" y2="22.03125"/>
|
||||
<rect fill="#d8d8d8" stroke="#000000" stroke-width="0" x="3.25" y="3.28125" width="4" height="4"/>
|
||||
<rect fill="#d8d8d8" stroke="#000000" stroke-width="0" x="10" y="3.28125" width="4" height="4"/>
|
||||
<rect fill="#d8d8d8" stroke="#000000" stroke-width="0" x="16.75" y="3.28125" width="4" height="4"/>
|
||||
<rect fill="#d8d8d8" stroke="#000000" stroke-width="0" x="3.28125" y="9.75" width="4" height="4"/>
|
||||
<rect fill="#d8d8d8" stroke="#000000" stroke-width="0" x="10.03125" y="9.75" width="4" height="4"/>
|
||||
<rect fill="#d8d8d8" stroke="#000000" stroke-width="0" x="16.78125" y="9.75" width="4" height="4"/>
|
||||
<rect fill="#d8d8d8" stroke="#000000" stroke-width="0" x="3.3125" y="16.59375" width="4" height="4"/>
|
||||
<rect fill="#d8d8d8" stroke="#000000" stroke-width="0" x="10.0625" y="16.59375" width="4" height="4"/>
|
||||
<rect fill="#d8d8d8" stroke="#000000" stroke-width="0" x="16.8125" y="16.59375" width="4" height="4"/>
|
||||
</g>
|
||||
</svg>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2 KiB |
|
@ -540,6 +540,18 @@
|
|||
</svg>
|
||||
</g>
|
||||
|
||||
<g id="context_menu">
|
||||
<svg width="120" height="120" xmlns="http://www.w3.org/2000/svg">
|
||||
<path stroke-width="0" id="svg_11" d="m4.5,46.5l52,0l-26,38l-26,-38z" stroke="#000" fill="#000"/>
|
||||
<g id="svg_16">
|
||||
<line stroke-width="10" id="svg_12" y2="27.5" x2="117.5" y1="27.5" x1="59.5" stroke="#000" fill="#000"/>
|
||||
<line id="svg_13" stroke-width="10" y2="51.5" x2="117.5" y1="51.5" x1="59.5" stroke="#000" fill="#000"/>
|
||||
<line id="svg_14" stroke-width="10" y2="73.5" x2="117.5" y1="73.5" x1="59.5" stroke="#000" fill="#000"/>
|
||||
<line id="svg_15" stroke-width="10" y2="97.5" x2="117.5" y1="97.5" x1="59.5" stroke="#000" fill="#000"/>
|
||||
</g>
|
||||
</svg>
|
||||
</g>
|
||||
|
||||
<g id="move_bottom">
|
||||
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23 23">
|
||||
<defs>
|
||||
|
@ -721,8 +733,8 @@
|
|||
</g>
|
||||
|
||||
<g id="fontsize">
|
||||
<svg width="50" height="50" xmlns="http://www.w3.org/2000/svg" xmlns:xml="http://www.w3.org/XML/1998/namespace">
|
||||
<text fill="#606060" stroke="none" x="14.451" y="41.4587" id="svg_2" font-size="26" font-family="serif" text-anchor="middle" xml:space="preserve">T</text>
|
||||
<svg width="50" height="50" xmlns="http://www.w3.org/2000/svg">
|
||||
<text fill="#606060" stroke="none" x="14.451" y="41.4587" id="svg_2" font-size="26" font-family="serif" text-anchor="middle">T</text>
|
||||
<text fill="#000000" stroke="none" x="28.853" y="41.8685" font-size="52" font-family="serif" text-anchor="middle" xml:space="preserve" id="svg_3">T</text>
|
||||
</svg>
|
||||
</g>
|
||||
|
|
|
@ -12,4 +12,4 @@
|
|||
* Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/
|
||||
*/
|
||||
|
||||
(function(b){b.hotkeys={version:"0.8",specialKeys:{8:"backspace",9:"tab",13:"return",16:"shift",17:"ctrl",18:"alt",19:"pause",20:"capslock",27:"esc",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",45:"insert",46:"del",96:"0",97:"1",98:"2",99:"3",100:"4",101:"5",102:"6",103:"7",104:"8",105:"9",106:"*",107:"+",109:"-",110:".",111:"/",112:"f1",113:"f2",114:"f3",115:"f4",116:"f5",117:"f6",118:"f7",119:"f8",120:"f9",121:"f10",122:"f11",123:"f12",144:"numlock",145:"scroll",191:"/",224:"meta"},shiftNums:{"`":"~","1":"!","2":"@","3":"#","4":"$","5":"%","6":"^","7":"&","8":"*","9":"(","0":")","-":"_","=":"+",";":": ","'":'"',",":"<",".":">","/":"?","\\":"|"}};function a(d){if(typeof d.data!=="string"){return}var c=d.handler,e=d.data.toLowerCase().split(" ");d.handler=function(n){if(this!==n.target&&(/textarea|select/i.test(n.target.nodeName)||n.target.type==="text")){return}var h=n.type!=="keypress"&&b.hotkeys.specialKeys[n.which],o=String.fromCharCode(n.which).toLowerCase(),k,m="",g={};if(n.altKey&&h!=="alt"){m+="alt+"}if(n.ctrlKey&&h!=="ctrl"){m+="ctrl+"}if(n.metaKey&&!n.ctrlKey&&h!=="meta"){m+="meta+"}if(n.shiftKey&&h!=="shift"){m+="shift+"}if(h){g[m+h]=true}else{g[m+o]=true;g[m+b.hotkeys.shiftNums[o]]=true;if(m==="shift+"){g[b.hotkeys.shiftNums[o]]=true}}for(var j=0,f=e.length;j<f;j++){if(g[e[j]]){return c.apply(this,arguments)}}}}b.each(["keydown","keyup","keypress"],function(){b.event.special[this]={add:a}})})(jQuery);
|
||||
(function(b){b.hotkeys={version:"0.8",specialKeys:{8:"backspace",9:"tab",13:"return",16:"shift",17:"ctrl",18:"alt",19:"pause",20:"capslock",27:"esc",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",45:"insert",46:"del",96:"0",97:"1",98:"2",99:"3",100:"4",101:"5",102:"6",103:"7",104:"8",105:"9",106:"*",107:"+",109:"-",110:".",111:"/",112:"f1",113:"f2",114:"f3",115:"f4",116:"f5",117:"f6",118:"f7",119:"f8",120:"f9",121:"f10",122:"f11",123:"f12",144:"numlock",145:"scroll",191:"/",224:"meta",219:"[",221:"]"},shiftNums:{"`":"~","1":"!","2":"@","3":"#","4":"$","5":"%","6":"^","7":"&","8":"*","9":"(","0":")","-":"_","=":"+",";":": ","'":'"',",":"<",".":">","/":"?","\\":"|"}};function a(d){if(typeof d.data!=="string"){return}var c=d.handler,e=d.data.toLowerCase().split(" ");d.handler=function(n){if(this!==n.target&&(/textarea|select/i.test(n.target.nodeName)||n.target.type==="text")){return}var h=n.type!=="keypress"&&b.hotkeys.specialKeys[n.which],o=String.fromCharCode(n.which).toLowerCase(),k,m="",g={};if(n.altKey&&h!=="alt"){m+="alt+"}if(n.ctrlKey&&h!=="ctrl"){m+="ctrl+"}if(n.metaKey&&!n.ctrlKey&&h!=="meta"){m+="meta+"}if(n.shiftKey&&h!=="shift"){m+="shift+"}if(h){g[m+h]=true}else{g[m+o]=true;g[m+b.hotkeys.shiftNums[o]]=true;if(m==="shift+"){g[b.hotkeys.shiftNums[o]]=true}}for(var j=0,f=e.length;j<f;j++){if(g[e[j]]){return c.apply(this,arguments)}}}}b.each(["keydown","keyup","keypress"],function(){b.event.special[this]={add:a}})})(jQuery);
|
|
@ -190,7 +190,7 @@
|
|||
padding: 0px;
|
||||
padding-left: 2px;
|
||||
padding-right: 2px;
|
||||
width: 106px;
|
||||
width: 123px;
|
||||
height: 20px;
|
||||
border-right: 1px solid #FFFFFF;
|
||||
border-bottom: 1px solid #FFFFFF;
|
||||
|
@ -212,6 +212,10 @@
|
|||
margin-right: 3px;
|
||||
}
|
||||
|
||||
#svg_editor .layer_button:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
#svg_editor .layer_buttonpressed {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
|
@ -226,7 +230,7 @@
|
|||
#svg_editor #layerlist {
|
||||
margin: 1px;
|
||||
padding: 0px;
|
||||
width: 110px;
|
||||
width: 127px;
|
||||
border-collapse: collapse;
|
||||
border: 1px solid #808080;
|
||||
background-color: #FFFFFF;
|
||||
|
@ -444,16 +448,7 @@
|
|||
fill: #FFF !important;
|
||||
}
|
||||
|
||||
#svg_editor #selected_panel,
|
||||
#svg_editor #multiselected_panel,
|
||||
#svg_editor #g_panel,
|
||||
#svg_editor #rect_panel,
|
||||
#svg_editor #circle_panel,
|
||||
#svg_editor #ellipse_panel,
|
||||
#svg_editor #line_panel,
|
||||
#svg_editor #image_panel,
|
||||
#svg_editor #text_panel,
|
||||
#svg_editor #path_node_panel {
|
||||
#tools_top div[id$="_panel"]:not(#editor_panel):not(#history_panel) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
@ -934,6 +929,16 @@ span.zoom_tool {
|
|||
z-index: 6;
|
||||
}
|
||||
|
||||
#save_output_btns {
|
||||
display: none;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#save_output_btns p {
|
||||
margin: .5em 1.5em;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#bg_blocks {
|
||||
overflow: auto;
|
||||
margin-left: 30px;
|
||||
|
@ -1005,8 +1010,9 @@ span.zoom_tool {
|
|||
color: #444;
|
||||
}
|
||||
|
||||
#canvas_title {
|
||||
#canvas_title, #canvas_bg_url {
|
||||
display: block;
|
||||
width: 96%;
|
||||
}
|
||||
|
||||
#svg_source_editor #svg_source_textarea {
|
||||
|
@ -1214,4 +1220,76 @@ span.zoom_tool {
|
|||
-webkit-border-radius: 0px;
|
||||
}
|
||||
|
||||
/* Generic context menu styles */
|
||||
.contextMenu {
|
||||
position: absolute;
|
||||
z-index: 99999;
|
||||
border: solid 1px rgba(0,0,0,.33);
|
||||
background: rgba(255,255,255,.95);
|
||||
padding: 5px 0;
|
||||
margin: 0px;
|
||||
display: none;
|
||||
font: 14px/17px Lucida Sans, Helvetica, Verdana, sans-serif;
|
||||
border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
-moz-box-shadow: 2px 5px 10px rgba(0,0,0,.3);
|
||||
-webkit-box-shadow: 2px 5px 10px rgba(0,0,0,.3);
|
||||
box-shadow: 2px 5px 10px rgba(0,0,0,.3);
|
||||
}
|
||||
|
||||
.contextMenu LI {
|
||||
list-style: none;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.contextMenu A {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
color: #222;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
line-height: 20px;
|
||||
height: 20px;
|
||||
background-position: 6px center;
|
||||
background-repeat: no-repeat;
|
||||
outline: none;
|
||||
padding: 0px 15px 1px 20px;
|
||||
}
|
||||
|
||||
.contextMenu LI.hover A {
|
||||
background-color: #2e5dea;
|
||||
color: white;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.contextMenu LI.disabled A {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.contextMenu LI.hover.disabled A {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.contextMenu LI.separator {
|
||||
border-top: solid 1px #E3E3E3;
|
||||
padding-top: 5px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
/*
|
||||
Adding Icons
|
||||
|
||||
You can add icons to the context menu by adding
|
||||
classes to the respective LI element(s)
|
||||
*/
|
||||
/*
|
||||
|
||||
.contextMenu LI.edit A { background-image: url(images/page_white_edit.png); }
|
||||
.contextMenu LI.cut A { background-image: url(images/cut.png); }
|
||||
.contextMenu LI.copy A { background-image: url(images/page_white_copy.png); }
|
||||
.contextMenu LI.paste A { background-image: url(images/page_white_paste.png); }
|
||||
.contextMenu LI.delete A { background-image: url(images/page_white_delete.png); }
|
||||
.contextMenu LI.quit A { background-image: url(images/door.png); }
|
||||
*/
|
||||
foreignObject {line-height:1.0}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
<script type="text/javascript" src="svgicons/jquery.svgicons.js"></script>
|
||||
<script type="text/javascript" src="jquerybbq/jquery.bbq.min.js"></script>
|
||||
<script type="text/javascript" src="spinbtn/JQuerySpinBtn.js"></script>
|
||||
<script type="text/javascript" src="contextmenu/jquery.contextMenu.js"></script>
|
||||
<script type="text/javascript" src="svgcanvas.js"></script>
|
||||
<script type="text/javascript" src="svg-editor.js"></script>
|
||||
<script type="text/javascript" src="locale/locale.js"></script>
|
||||
|
@ -61,6 +62,7 @@ script type="text/javascript" src="locale/locale.min.js"></script-->
|
|||
<div id="layer_rename" class="layer_button" title="Rename Layer"></div>
|
||||
<div id="layer_up" class="layer_button" title="Move Layer Up"></div>
|
||||
<div id="layer_down" class="layer_button" title="Move Layer Down"></div>
|
||||
<div id="layer_moreopts" class="layer_button" title="More Options"></div>
|
||||
</fieldset>
|
||||
|
||||
<table id="layerlist">
|
||||
|
@ -562,6 +564,10 @@ script type="text/javascript" src="locale/locale.min.js"></script-->
|
|||
<button id="tool_source_save">Apply Changes</button>
|
||||
<button id="tool_source_cancel">Cancel</button>
|
||||
</div>
|
||||
<div id="save_output_btns">
|
||||
<p id="copy_save_note">Copy the contents of this box into a text editor, then save the file with a .svg extension.</p>
|
||||
<button id="copy_save_done">Done</button>
|
||||
</div>
|
||||
<form>
|
||||
<textarea id="svg_source_textarea" spellcheck="false"></textarea>
|
||||
</form>
|
||||
|
@ -581,7 +587,7 @@ script type="text/javascript" src="locale/locale.min.js"></script-->
|
|||
<legend id="svginfo_image_props">Image Properties</legend>
|
||||
<label>
|
||||
<span id="svginfo_title">Title:</span>
|
||||
<input type="text" id="canvas_title" size="24"/>
|
||||
<input type="text" id="canvas_title"/>
|
||||
</label>
|
||||
|
||||
<fieldset id="change_resolution">
|
||||
|
@ -650,10 +656,16 @@ script type="text/javascript" src="locale/locale.min.js"></script-->
|
|||
<fieldset id="change_background">
|
||||
<legend id="svginfo_change_background">Editor Background</legend>
|
||||
<div id="bg_blocks"></div>
|
||||
<label><span id="svginfo_bg_url">URL:</span> <input type="text" id="canvas_bg_url" size="21"/></label>
|
||||
<label><span id="svginfo_bg_url">URL:</span> <input type="text" id="canvas_bg_url"/></label>
|
||||
<p id="svginfo_bg_note">Note: Background will not be saved with image.</p>
|
||||
</fieldset>
|
||||
|
||||
<fieldset id="change_grid">
|
||||
<legend id="svginfo_grid_settings">Grid</legend>
|
||||
<label><span id="svginfo_snap_onoff">Snapping on/off</span><input type="checkbox" value="snapping_on" id="grid_snapping_on"></label>
|
||||
<label><span id="svginfo_snap_step">Snapping Step-Size:</span> <input type="text" id="grid_snapping_step" size="3" value="10"/></label>
|
||||
</fieldset>
|
||||
|
||||
</fieldset>
|
||||
|
||||
</div>
|
||||
|
@ -667,5 +679,23 @@ script type="text/javascript" src="locale/locale.min.js"></script-->
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<ul id="cmenu_canvas" class="contextMenu">
|
||||
<li><a href="#cut">Cut</a></li>
|
||||
<li><a href="#copy">Copy</a></li>
|
||||
<li><a href="#paste">Paste</a></li>
|
||||
<li><a href="#paste_in_place">Paste in Place</a></li>
|
||||
<li class="separator"><a href="#delete">Delete</a></li>
|
||||
<li class="separator"><a href="#move_up">Bring Forward</a></li>
|
||||
<li><a href="#move_down">Send Backward</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<ul id="cmenu_layers" class="contextMenu">
|
||||
<li><a href="#dupe">Duplicate Layer...</a></li>
|
||||
<li><a href="#delete">Delete Layer</a></li>
|
||||
<li><a href="#merge_down">Merge Down</a></li>
|
||||
<li><a href="#merge_all">Merge All</a></li>
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
*/
|
||||
|
||||
(function() {
|
||||
// TODO: Find out what causes bugs in jQuery animate for IE9
|
||||
if($.browser.msie) $.fx.off = true;
|
||||
|
||||
if(!window.svgEditor) window.svgEditor = function($) {
|
||||
var svgCanvas;
|
||||
|
@ -46,10 +48,12 @@
|
|||
langPath: 'locale/',
|
||||
extPath: 'extensions/',
|
||||
jGraduatePath: 'jgraduate/images/',
|
||||
extensions: ['ext-markers.js','ext-connector.js', 'ext-eyedropper.js', 'ext-imagelib.js', 'ext-itex.js'],
|
||||
extensions: ['ext-markers.js','ext-connector.js', 'ext-eyedropper.js', 'ext-imagelib.js','ext-grid.js', 'ext-itex.js'],
|
||||
initTool: 'select',
|
||||
wireframe: false,
|
||||
colorPickerCSS: null
|
||||
colorPickerCSS: null,
|
||||
gridSnapping: false,
|
||||
snappingStep: 5
|
||||
},
|
||||
uiStrings = Editor.uiStrings = {
|
||||
"invalidAttrValGiven":"Invalid value given",
|
||||
|
@ -435,13 +439,14 @@
|
|||
"#aaaaff", "#d4aaff", "#ffaaff", "#ffaad4",
|
||||
];
|
||||
|
||||
isMac = false, //(navigator.platform.indexOf("Mac") != -1);
|
||||
modKey = "", //(isMac ? "meta+" : "ctrl+");
|
||||
isMac = (navigator.platform.indexOf("Mac") != -1);
|
||||
modKey = (isMac ? "meta+" : "ctrl+"); // ⌘
|
||||
path = svgCanvas.pathActions,
|
||||
undoMgr = svgCanvas.undoMgr,
|
||||
Utils = svgCanvas.Utils,
|
||||
default_img_url = curConfig.imgPath + "logo.png",
|
||||
workarea = $("#workarea"),
|
||||
canv_menu = $("#cmenu_canvas"),
|
||||
show_save_warning = false,
|
||||
exportWindow = null,
|
||||
tool_scale = 1;
|
||||
|
@ -496,9 +501,12 @@
|
|||
}());
|
||||
|
||||
var setSelectMode = function() {
|
||||
$('.tool_button_current').removeClass('tool_button_current').addClass('tool_button');
|
||||
$('#tool_select').addClass('tool_button_current').removeClass('tool_button');
|
||||
$('#styleoverrides').text('#svgcanvas svg *{cursor:move;pointer-events:all} #svgcanvas svg{cursor:default}');
|
||||
var curr = $('.tool_button_current');
|
||||
if(curr[0].id !== 'tool_select') {
|
||||
curr.removeClass('tool_button_current').addClass('tool_button');
|
||||
$('#tool_select').addClass('tool_button_current').removeClass('tool_button');
|
||||
$('#styleoverrides').text('#svgcanvas svg *{cursor:move;pointer-events:all} #svgcanvas svg{cursor:default}');
|
||||
}
|
||||
svgCanvas.setMode('select');
|
||||
};
|
||||
|
||||
|
@ -539,6 +547,15 @@
|
|||
|
||||
// Opens the SVG in new window, with warning about Mozilla bug #308590 when applicable
|
||||
|
||||
var ua = navigator.userAgent;
|
||||
|
||||
// Chrome 5 (and 6?) don't allow saving, show source instead ( http://code.google.com/p/chromium/issues/detail?id=46735 )
|
||||
// IE9 doesn't allow standalone Data URLs ( https://connect.microsoft.com/IE/feedback/details/542600/data-uri-images-fail-when-loaded-by-themselves )
|
||||
if((~ua.indexOf('Chrome') && $.browser.version >= 533) || ~ua.indexOf('MSIE')) {
|
||||
showSourceEditor(0,true);
|
||||
return;
|
||||
}
|
||||
|
||||
var win = window.open("data:image/svg+xml;base64," + Utils.encode64(svg));
|
||||
|
||||
// Alert will only appear the first time saved OR the first time the bug is encountered
|
||||
|
@ -548,7 +565,7 @@
|
|||
var note = uiStrings.saveFromBrowser.replace('%s', 'SVG');
|
||||
|
||||
// Check if FF and has <defs/>
|
||||
if(navigator.userAgent.indexOf('Gecko/') !== -1) {
|
||||
if(ua.indexOf('Gecko/') !== -1) {
|
||||
if(svg.indexOf('<defs') !== -1) {
|
||||
note += "\n\n" + uiStrings.defsFailOnSave;
|
||||
$.pref('save_notice_done', 'all');
|
||||
|
@ -576,25 +593,25 @@
|
|||
|
||||
c.width = svgCanvas.contentW;
|
||||
c.height = svgCanvas.contentH;
|
||||
canvg(c, data.svg);
|
||||
var datauri = c.toDataURL('image/png');
|
||||
exportWindow.location.href = datauri;
|
||||
|
||||
var done = $.pref('export_notice_done');
|
||||
if(done !== "all") {
|
||||
var note = uiStrings.saveFromBrowser.replace('%s', 'PNG');
|
||||
|
||||
// Check if there's issues
|
||||
if(issues.length) {
|
||||
var pre = "\n \u2022 ";
|
||||
note += ("\n\n" + uiStrings.noteTheseIssues + pre + issues.join(pre));
|
||||
}
|
||||
|
||||
// Note that this will also prevent the notice even though new issues may appear later.
|
||||
// May want to find a way to deal with that without annoying the user
|
||||
$.pref('export_notice_done', 'all');
|
||||
exportWindow.alert(note);
|
||||
}
|
||||
canvg(c, data.svg, {renderCallback: function() {
|
||||
var datauri = c.toDataURL('image/png');
|
||||
exportWindow.location.href = datauri;
|
||||
var done = $.pref('export_notice_done');
|
||||
if(done !== "all") {
|
||||
var note = uiStrings.saveFromBrowser.replace('%s', 'PNG');
|
||||
|
||||
// Check if there's issues
|
||||
if(issues.length) {
|
||||
var pre = "\n \u2022 ";
|
||||
note += ("\n\n" + uiStrings.noteTheseIssues + pre + issues.join(pre));
|
||||
}
|
||||
|
||||
// Note that this will also prevent the notice even though new issues may appear later.
|
||||
// May want to find a way to deal with that without annoying the user
|
||||
$.pref('export_notice_done', 'all');
|
||||
exportWindow.alert(note);
|
||||
}
|
||||
}});
|
||||
};
|
||||
|
||||
// called when we've selected a different element
|
||||
|
@ -610,7 +627,6 @@
|
|||
// select mode and this event fires - we need our UI to be in sync
|
||||
|
||||
if (mode != "multiselect" && !is_node) {
|
||||
setSelectMode();
|
||||
updateToolbar();
|
||||
}
|
||||
|
||||
|
@ -628,6 +644,10 @@
|
|||
|
||||
// called when any element has changed
|
||||
var elementChanged = function(window,elems) {
|
||||
if(svgCanvas.getMode() == "select") {
|
||||
setSelectMode();
|
||||
}
|
||||
|
||||
for (var i = 0; i < elems.length; ++i) {
|
||||
var elem = elems[i];
|
||||
|
||||
|
@ -712,7 +732,7 @@
|
|||
opts.fn();
|
||||
}
|
||||
if(opts.icon) {
|
||||
var icon = $.getSvgIcon(opts.icon).clone();
|
||||
var icon = $.getSvgIcon(opts.icon, true);
|
||||
} else {
|
||||
//
|
||||
var icon = $(opts.sel).children().eq(0).clone();
|
||||
|
@ -1345,10 +1365,8 @@
|
|||
|
||||
if(svgCanvas.addedNew) {
|
||||
if(elname == 'image') {
|
||||
var xlinkNS = "http://www.w3.org/1999/xlink";
|
||||
var href = elem.getAttributeNS(xlinkNS, "href");
|
||||
// Prompt for URL if not a data URL
|
||||
if(href.indexOf('data:') !== 0) {
|
||||
if(svgCanvas.getHref(elem).indexOf('data:') !== 0) {
|
||||
promptImgURL();
|
||||
}
|
||||
} else if(elname == 'text') {
|
||||
|
@ -1455,9 +1473,7 @@
|
|||
}
|
||||
} // text
|
||||
else if(el_name == 'image') {
|
||||
var xlinkNS="http://www.w3.org/1999/xlink";
|
||||
var href = elem.getAttributeNS(xlinkNS, "href");
|
||||
setImageURL(href);
|
||||
setImageURL(svgCanvas.getHref(elem));
|
||||
} // image
|
||||
else if(el_name == 'g' || el_name == 'use') {
|
||||
$('#container_panel').show();
|
||||
|
@ -1476,6 +1492,8 @@
|
|||
} // if (elem != null)
|
||||
else if (multiselected) {
|
||||
$('#multiselected_panel').show();
|
||||
} else {
|
||||
$('#cmenu_canvas li').disableContextMenuItems('#delete,#cut,#copy,#move_up,#move_down');
|
||||
}
|
||||
|
||||
// update history buttons
|
||||
|
@ -1497,6 +1515,9 @@
|
|||
if ( (elem && !is_node) || multiselected) {
|
||||
// update the selected elements' layer
|
||||
$('#selLayerNames').removeAttr('disabled').val(currentLayer);
|
||||
|
||||
// Enable regular menu options
|
||||
canv_menu.enableContextMenuItems('#delete,#cut,#copy,#move_down,#move_up');
|
||||
}
|
||||
else {
|
||||
$('#selLayerNames').attr('disabled', 'disabled');
|
||||
|
@ -1766,7 +1787,9 @@
|
|||
$('.tool_button_current').removeClass('tool_button_current').addClass('tool_button');
|
||||
$(button).addClass('tool_button_current').removeClass('tool_button');
|
||||
// when a tool is selected, we should deselect any currently selected elements
|
||||
svgCanvas.clearSelection();
|
||||
if(button !== '#tool_select') {
|
||||
svgCanvas.clearSelection();
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
|
@ -1851,8 +1874,11 @@
|
|||
}
|
||||
on_button = false;
|
||||
}).mousedown(function(evt) {
|
||||
var islib = $(evt.target).closest('div.tools_flyout').length;
|
||||
if(!islib) $('.tools_flyout:visible').fadeOut();
|
||||
// $(".contextMenu").hide();
|
||||
// console.log('cm', $(evt.target).closest('.contextMenu'));
|
||||
|
||||
var islib = $(evt.target).closest('div.tools_flyout, .contextMenu').length;
|
||||
if(!islib) $('.tools_flyout:visible,.contextMenu').fadeOut(250);
|
||||
});
|
||||
|
||||
overlay.bind('mousedown',function() {
|
||||
|
@ -2197,17 +2223,35 @@
|
|||
}
|
||||
};
|
||||
|
||||
var cutSelected = function() {
|
||||
if (selectedElement != null || multiselected) {
|
||||
svgCanvas.cutSelectedElements();
|
||||
}
|
||||
};
|
||||
|
||||
var copySelected = function() {
|
||||
if (selectedElement != null || multiselected) {
|
||||
svgCanvas.copySelectedElements();
|
||||
}
|
||||
};
|
||||
|
||||
var moveToTopSelected = function() {
|
||||
if (selectedElement != null) {
|
||||
svgCanvas.moveToTopSelectedElement();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var moveToBottomSelected = function() {
|
||||
if (selectedElement != null) {
|
||||
svgCanvas.moveToBottomSelectedElement();
|
||||
}
|
||||
};
|
||||
|
||||
var moveUpDownSelected = function(dir) {
|
||||
if (selectedElement != null) {
|
||||
svgCanvas.moveUpDownSelected(dir);
|
||||
}
|
||||
};
|
||||
|
||||
var convertToPath = function() {
|
||||
if (selectedElement != null) {
|
||||
|
@ -2422,9 +2466,13 @@
|
|||
$('#wireframe_rules').text(workarea.hasClass('wireframe') ? rule : "");
|
||||
}
|
||||
|
||||
var showSourceEditor = function(){
|
||||
var showSourceEditor = function(e, forSaving){
|
||||
if (editingsource) return;
|
||||
editingsource = true;
|
||||
|
||||
$('#save_output_btns').toggle(!!forSaving);
|
||||
$('#tool_source_back').toggle(!forSaving);
|
||||
|
||||
var str = svgCanvas.getSvgString();
|
||||
$('#svg_source_textarea').val(str);
|
||||
$('#svg_source_editor').fadeIn();
|
||||
|
@ -2463,6 +2511,12 @@
|
|||
if(url) {
|
||||
$('#canvas_bg_url').val(url);
|
||||
}
|
||||
$('grid_snapping_step').attr('value', curConfig.snappingStep);
|
||||
if (curConfig.gridSnapping == true) {
|
||||
$('#grid_snapping_on').attr('checked', 'checked');
|
||||
} else {
|
||||
$('#grid_snapping_on').removeAttr('checked');
|
||||
}
|
||||
|
||||
$('#svg_docprops').fadeIn();
|
||||
};
|
||||
|
@ -2549,6 +2603,10 @@
|
|||
// set icon size
|
||||
setIconSize($('#iconsize').val());
|
||||
|
||||
// set grid setting
|
||||
curConfig.gridSnapping = $('#grid_snapping_on').attr('checked');
|
||||
curConfig.snappingStep = $('#grid_snapping_step').val();
|
||||
|
||||
updateCanvas();
|
||||
hideDocProperties();
|
||||
};
|
||||
|
@ -2563,25 +2621,18 @@
|
|||
}
|
||||
|
||||
var setIcon = Editor.setIcon = function(elem, icon_id, forcedSize) {
|
||||
var icon = (typeof icon_id == 'string') ? $.getSvgIcon(icon_id) : icon_id;
|
||||
var icon = (typeof icon_id == 'string') ? $.getSvgIcon(icon_id, true) : icon_id;
|
||||
if(!icon) {
|
||||
console.log('NOTE: Icon image missing: ' + icon_id);
|
||||
return;
|
||||
}
|
||||
icon = icon.clone();
|
||||
$(elem).empty().append(icon);
|
||||
// if(forcedSize) {
|
||||
// var obj = {};
|
||||
// obj[elem + ' .svg_icon'] = forcedSize;
|
||||
// $.resizeSvgIcons(obj);
|
||||
// } else {
|
||||
// var size = curPrefs.iconsize;
|
||||
// if(size && size !== 'm') {
|
||||
// var icon_sizes = { s:16, m:24, l:32, xl:48}, obj = {};
|
||||
// obj[elem + ' .svg_icon'] = icon_sizes[size];
|
||||
// $.resizeSvgIcons(obj);
|
||||
// }
|
||||
// }
|
||||
try {
|
||||
icon = icon.clone();
|
||||
$(elem).empty().append(icon);
|
||||
} catch(e) {
|
||||
// icon = svgCanvas.copyElem(icon[0]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var ua_prefix;
|
||||
|
@ -2908,7 +2959,9 @@
|
|||
$('#change_image_url').click(promptImgURL);
|
||||
|
||||
function promptImgURL() {
|
||||
$.prompt(uiStrings.enterNewImgURL, default_img_url, function(url) {
|
||||
var curhref = svgCanvas.getHref(selectedElement);
|
||||
curhref = curhref.indexOf("data:") === 0?"":curhref;
|
||||
$.prompt(uiStrings.enterNewImgURL, curhref, function(url) {
|
||||
if(url) setImageURL(url);
|
||||
});
|
||||
}
|
||||
|
@ -2945,9 +2998,11 @@
|
|||
var i = shortcutButtons.length;
|
||||
while (i--) {
|
||||
var button = document.getElementById(shortcutButtons[i]);
|
||||
var title = button.title;
|
||||
var index = title.indexOf("Ctrl+");
|
||||
button.title = [title.substr(0,index), "Cmd+", title.substr(index+5)].join('');
|
||||
if (button != null) {
|
||||
var title = button.title;
|
||||
var index = title.indexOf("Ctrl+");
|
||||
button.title = [title.substr(0, index), "Cmd+", title.substr(index + 5)].join('');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3059,44 +3114,71 @@
|
|||
|
||||
operaRepaint();
|
||||
};
|
||||
|
||||
// set up gradients to be used for the buttons
|
||||
var svgdocbox = new DOMParser().parseFromString(
|
||||
'<svg xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%"\
|
||||
fill="#' + curConfig.initFill.color + '" opacity="' + curConfig.initFill.opacity + '"/>\
|
||||
<linearGradient id="gradbox_">\
|
||||
<stop stop-color="#000" offset="0.0"/>\
|
||||
<stop stop-color="#FF0000" offset="1.0"/>\
|
||||
</linearGradient></svg>', 'text/xml');
|
||||
|
||||
var boxgrad = svgdocbox.getElementById('gradbox_');
|
||||
boxgrad.id = 'gradbox_fill';
|
||||
svgdocbox.documentElement.setAttribute('width',16.5);
|
||||
$('#fill_color').append( document.importNode(svgdocbox.documentElement,true) );
|
||||
|
||||
boxgrad.id = 'gradbox_stroke';
|
||||
svgdocbox.documentElement.setAttribute('width',16.5);
|
||||
$('#stroke_color').append( document.importNode(svgdocbox.documentElement,true) );
|
||||
$('#stroke_color rect').attr({
|
||||
'fill': '#' + curConfig.initStroke.color,
|
||||
'opacity': curConfig.initStroke.opacity
|
||||
});
|
||||
|
||||
$('#stroke_width').val(curConfig.initStroke.width);
|
||||
$('#group_opacity').val(curConfig.initOpacity * 100);
|
||||
|
||||
// Use this SVG elem to test vectorEffect support
|
||||
var test_el = svgdocbox.documentElement.firstChild;
|
||||
test_el.setAttribute('style','vector-effect:non-scaling-stroke');
|
||||
var supportsNonSS = (test_el.style.vectorEffect == 'non-scaling-stroke');
|
||||
test_el.removeAttribute('style');
|
||||
|
||||
// Use this to test support for blur element. Seems to work to test support in Webkit
|
||||
var blur_test = svgdocbox.createElementNS('http://www.w3.org/2000/svg', 'feGaussianBlur');
|
||||
if(typeof blur_test.stdDeviationX === "undefined") {
|
||||
$('#tool_blur').hide();
|
||||
if(window.DOMParser) {
|
||||
// set up gradients to be used for the buttons
|
||||
var svgdocbox = new DOMParser().parseFromString(
|
||||
'<svg xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%"\
|
||||
fill="#' + curConfig.initFill.color + '" opacity="' + curConfig.initFill.opacity + '"/>\
|
||||
<linearGradient id="gradbox_">\
|
||||
<stop stop-color="#000" offset="0.0"/>\
|
||||
<stop stop-color="#FF0000" offset="1.0"/>\
|
||||
</linearGradient></svg>', 'text/xml');
|
||||
var docElem = svgdocbox.documentElement;
|
||||
|
||||
|
||||
var boxgrad = svgdocbox.getElementById('gradbox_');
|
||||
boxgrad.id = 'gradbox_fill';
|
||||
docElem.setAttribute('width',16.5);
|
||||
$('#fill_color').append( document.importNode(docElem,true) );
|
||||
|
||||
boxgrad.id = 'gradbox_stroke';
|
||||
docElem.setAttribute('width',16.5);
|
||||
$('#stroke_color').append( document.importNode(docElem,true) );
|
||||
$('#stroke_color rect').attr({
|
||||
'fill': '#' + curConfig.initStroke.color,
|
||||
'opacity': curConfig.initStroke.opacity
|
||||
});
|
||||
|
||||
$('#stroke_width').val(curConfig.initStroke.width);
|
||||
$('#group_opacity').val(curConfig.initOpacity * 100);
|
||||
|
||||
// Use this SVG elem to test vectorEffect support
|
||||
var test_el = docElem.firstChild;
|
||||
test_el.setAttribute('style','vector-effect:non-scaling-stroke');
|
||||
var supportsNonSS = (test_el.style.vectorEffect == 'non-scaling-stroke');
|
||||
test_el.removeAttribute('style');
|
||||
|
||||
// Use this to test support for blur element. Seems to work to test support in Webkit
|
||||
var blur_test = svgdocbox.createElementNS('http://www.w3.org/2000/svg', 'feGaussianBlur');
|
||||
if(typeof blur_test.stdDeviationX === "undefined") {
|
||||
$('#tool_blur').hide();
|
||||
}
|
||||
$(blur_test).remove();
|
||||
} else {
|
||||
var svgns = "http://www.w3.org/2000/svg";
|
||||
var svgdocbox = document.createElementNS(svgns, 'svg');
|
||||
var rect = svgCanvas.addSvgElementFromJson({
|
||||
element: 'rect',
|
||||
attr: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
fill: '#' + curConfig.initFill.color,
|
||||
opacity: curConfig.initFill.opacity
|
||||
}
|
||||
});
|
||||
svgdocbox.appendChild(rect);
|
||||
var linearGradient = svgCanvas.addSvgElementFromJson({
|
||||
element: 'linearGradient',
|
||||
attr: {
|
||||
id: 'gradbox_'
|
||||
}
|
||||
});
|
||||
svgdocbox.appendChild(linearGradient);
|
||||
var docElem = svgdocbox;
|
||||
}
|
||||
$(blur_test).remove();
|
||||
|
||||
|
||||
|
||||
// Test for embedImage support (use timeout to not interfere with page load)
|
||||
setTimeout(function() {
|
||||
|
@ -3499,17 +3581,17 @@
|
|||
{sel:'#tool_text', fn: clickText, evt: 'click', key: 7},
|
||||
{sel:'#tool_image', fn: clickImage, evt: 'mouseup', key: 8},
|
||||
{sel:'#tool_zoom', fn: clickZoom, evt: 'mouseup', key: 9},
|
||||
{sel:'#tool_clear', fn: clickClear, evt: 'mouseup', key: [modKey+'N', true]},
|
||||
{sel:'#tool_save', fn: function() { editingsource?saveSourceEditor():clickSave()}, evt: 'mouseup', key: [modKey+'S', true]},
|
||||
{sel:'#tool_clear', fn: clickClear, evt: 'mouseup', key: ['N', true]},
|
||||
{sel:'#tool_save', fn: function() { editingsource?saveSourceEditor():clickSave()}, evt: 'mouseup', key: ['S', true]},
|
||||
{sel:'#tool_export', fn: clickExport, evt: 'mouseup'},
|
||||
{sel:'#tool_open', fn: clickOpen, evt: 'mouseup', key: [modKey+'O', true]},
|
||||
{sel:'#tool_open', fn: clickOpen, evt: 'mouseup', key: ['O', true]},
|
||||
{sel:'#tool_import', fn: clickImport, evt: 'mouseup'},
|
||||
{sel:'#tool_source', fn: showSourceEditor, evt: 'click', key: ['U', true]},
|
||||
{sel:'#tool_wireframe', fn: clickWireframe, evt: 'click', key: ['F', true]},
|
||||
{sel:'#tool_source_cancel,#svg_source_overlay,#tool_docprops_cancel', fn: cancelOverlays, evt: 'click', key: ['esc', false, false], hidekey: true},
|
||||
{sel:'#tool_source_save', fn: saveSourceEditor, evt: 'click'},
|
||||
{sel:'#tool_docprops_save', fn: saveDocProperties, evt: 'click'},
|
||||
{sel:'#tool_docprops', fn: showDocProperties, evt: 'mouseup', key: [modKey+'P', true]},
|
||||
{sel:'#tool_docprops', fn: showDocProperties, evt: 'mouseup', key: ['P', true]},
|
||||
{sel:'#tool_delete,#tool_delete_multi', fn: deleteSelected, evt: 'click', key: ['del/backspace', true]},
|
||||
{sel:'#tool_reorient', fn: reorientPath, evt: 'click'},
|
||||
{sel:'#tool_node_link', fn: linkControlPoints, evt: 'click'},
|
||||
|
@ -3520,10 +3602,10 @@
|
|||
{sel:'#tool_move_top', fn: moveToTopSelected, evt: 'click', key: 'shift+up'},
|
||||
{sel:'#tool_move_bottom', fn: moveToBottomSelected, evt: 'click', key: 'shift+down'},
|
||||
{sel:'#tool_topath', fn: convertToPath, evt: 'click'},
|
||||
{sel:'#tool_undo', fn: clickUndo, evt: 'click', key: [modKey+'Z', true]},
|
||||
{sel:'#tool_redo', fn: clickRedo, evt: 'click', key: [modKey+'Y', true]},
|
||||
{sel:'#tool_clone,#tool_clone_multi', fn: clickClone, evt: 'click', key: [modKey+'C', true]},
|
||||
{sel:'#tool_group', fn: clickGroup, evt: 'click', key: [modKey+'G', true]},
|
||||
{sel:'#tool_undo', fn: clickUndo, evt: 'click', key: ['Z', true]},
|
||||
{sel:'#tool_redo', fn: clickRedo, evt: 'click', key: ['Y', true]},
|
||||
{sel:'#tool_clone,#tool_clone_multi', fn: clickClone, evt: 'click', key: ['C', true]},
|
||||
{sel:'#tool_group', fn: clickGroup, evt: 'click', key: ['G', true]},
|
||||
{sel:'#tool_ungroup', fn: clickGroup, evt: 'click'},
|
||||
{sel:'#tool_unlink_use', fn: clickGroup, evt: 'click'},
|
||||
{sel:'[id^=tool_align]', fn: clickAlign, evt: 'click'},
|
||||
|
@ -3532,15 +3614,18 @@
|
|||
// {sel:'#tools_ellipse_show', fn: clickEllipse, evt: 'click'},
|
||||
{sel:'#tool_bold', fn: clickBold, evt: 'mousedown'},
|
||||
{sel:'#tool_italic', fn: clickItalic, evt: 'mousedown'},
|
||||
{sel:'#sidepanel_handle', fn: toggleSidePanel, key: [modKey+'X']},
|
||||
{sel:'#sidepanel_handle', fn: toggleSidePanel, key: ['X']},
|
||||
{sel:'#copy_save_done', fn: cancelOverlays, evt: 'click'},
|
||||
|
||||
// Shortcuts not associated with buttons
|
||||
{key: 'shift+left', fn: function(){rotateSelected(0)}},
|
||||
{key: 'shift+right', fn: function(){rotateSelected(1)}},
|
||||
{key: 'shift+O', fn: selectPrev},
|
||||
{key: 'shift+P', fn: selectNext},
|
||||
{key: ['ctrl+up', true], fn: function(){zoomImage(2);}},
|
||||
{key: ['ctrl+down', true], fn: function(){zoomImage(.5);}},
|
||||
{key: [modKey+'up', true], fn: function(){zoomImage(2);}},
|
||||
{key: [modKey+'down', true], fn: function(){zoomImage(.5);}},
|
||||
{key: [modKey+'[', true], fn: function(){moveUpDownSelected('Down');}},
|
||||
{key: [modKey+']', true], fn: function(){moveUpDownSelected('Up');}},
|
||||
{key: ['up', true], fn: function(){moveSelected(0,-1);}},
|
||||
{key: ['down', true], fn: function(){moveSelected(0,1);}},
|
||||
{key: ['left', true], fn: function(){moveSelected(-1,0);}},
|
||||
|
@ -3705,6 +3790,48 @@
|
|||
$('#blur').SpinButton({ step: .1, min: 0, max: 10, callback: changeBlur });
|
||||
$('#zoom').SpinButton({ min: 0.001, max: 10000, step: 50, stepfunc: stepZoom, callback: changeZoom });
|
||||
|
||||
$("#workarea").contextMenu({
|
||||
menu: 'cmenu_canvas',
|
||||
inSpeed: 0
|
||||
},
|
||||
function(action, el, pos) {
|
||||
switch ( action ) {
|
||||
case 'delete':
|
||||
deleteSelected();
|
||||
break;
|
||||
case 'cut':
|
||||
cutSelected();
|
||||
break;
|
||||
case 'copy':
|
||||
copySelected();
|
||||
break;
|
||||
case 'paste':
|
||||
svgCanvas.pasteElements();
|
||||
break;
|
||||
case 'paste_in_place':
|
||||
svgCanvas.pasteElements('in_place');
|
||||
break;
|
||||
case 'move_down':
|
||||
moveUpDownSelected('Down');
|
||||
break;
|
||||
case 'move_up':
|
||||
moveUpDownSelected('Up');
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if(svgCanvas.clipBoard.length) {
|
||||
canv_menu.enableContextMenuItems('#paste,#paste_in_place');
|
||||
}
|
||||
});
|
||||
|
||||
$('.contextMenu li').mousedown(function(ev) {
|
||||
ev.preventDefault();
|
||||
})
|
||||
|
||||
$('#cmenu_canvas li').disableContextMenu();
|
||||
canv_menu.enableContextMenuItems('#delete,#cut,#copy');
|
||||
|
||||
window.onbeforeunload = function() {
|
||||
// Suppress warning if page is empty
|
||||
if(undoMgr.getUndoStackSize() === 0) {
|
||||
|
@ -3835,7 +3962,7 @@
|
|||
updateCanvas(true);
|
||||
// });
|
||||
|
||||
// var revnums = "svg-editor.js ($Rev: 1659 $) ";
|
||||
// var revnums = "svg-editor.js ($Rev: 1706 $) ";
|
||||
// revnums += svgCanvas.getVersion();
|
||||
// $('#copyright')[0].setAttribute("title", revnums);
|
||||
|
||||
|
@ -3996,7 +4123,7 @@
|
|||
Editor.addExtension = function() {
|
||||
var args = arguments;
|
||||
$(function() {
|
||||
svgCanvas.addExtension.apply(this, args);
|
||||
if(svgCanvas) svgCanvas.addExtension.apply(this, args);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -128,7 +128,40 @@ $(function() {
|
|||
|
||||
|
||||
(function($) {
|
||||
var svg_icons = {};
|
||||
function makeSVG(el) {
|
||||
// manually create a copy of the element
|
||||
var new_el = document.createElementNS(el.namespaceURI, el.nodeName);
|
||||
$.each(el.attributes, function(i, attr) {
|
||||
var ns = attr.namespaceURI;
|
||||
if(ns) {
|
||||
new_el.setAttributeNS(ns, attr.nodeName, attr.nodeValue);
|
||||
} else {
|
||||
new_el.setAttribute(attr.nodeName, attr.nodeValue);
|
||||
}
|
||||
if(attr.nodeName == 'transform') {
|
||||
|
||||
console.log('val1:', attr.nodeValue);
|
||||
console.log('val2:', new_el.getAttribute('transform'));
|
||||
}
|
||||
});
|
||||
|
||||
// now create copies of all children
|
||||
$.each(el.childNodes, function(i, child) {
|
||||
switch(child.nodeType) {
|
||||
case 1: // element node
|
||||
new_el.appendChild(makeSVG(child));
|
||||
break;
|
||||
case 3: // text node
|
||||
new_el.textContent = child.nodeValue;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
return new_el;
|
||||
}
|
||||
|
||||
var svg_icons = {}, fixIDs;
|
||||
|
||||
$.svgIcons = function(file, opts) {
|
||||
var svgns = "http://www.w3.org/2000/svg",
|
||||
|
@ -168,7 +201,19 @@ $(function() {
|
|||
});
|
||||
} else {
|
||||
if(err.responseXML) {
|
||||
// Is there a non-ActiveX solution in IE9?
|
||||
svgdoc = err.responseXML;
|
||||
|
||||
if(!svgdoc.childNodes.length) {
|
||||
if(window.ActiveXObject) {
|
||||
svgdoc = new ActiveXObject("Microsoft.XMLDOM");
|
||||
svgdoc.loadXML(err.responseText);
|
||||
} else {
|
||||
$(useFallback);
|
||||
}
|
||||
} else {
|
||||
$(useFallback);
|
||||
}
|
||||
$(function() {
|
||||
getIcons('ajax');
|
||||
});
|
||||
|
@ -220,20 +265,29 @@ $(function() {
|
|||
}
|
||||
}
|
||||
});
|
||||
elems = $(svgdoc.firstChild).children(); //.getElementsByTagName('foreignContent');
|
||||
var testSrc = data_pre + 'PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNzUiIGhlaWdodD0iMjc1Ij48L3N2Zz4%3D';
|
||||
|
||||
testImg = $(new Image()).attr({
|
||||
src: testSrc,
|
||||
width: 0,
|
||||
height: 0
|
||||
}).appendTo('body')
|
||||
.load(function () {
|
||||
// Safari 4 crashes, Opera and Chrome don't
|
||||
makeIcons(!isSafari);
|
||||
}).error(function () {
|
||||
makeIcons();
|
||||
});
|
||||
elems = $(svgdoc.firstChild).children(); //.getElementsByTagName('foreignContent');
|
||||
|
||||
if(!opts.no_img) {
|
||||
|
||||
var testSrc = data_pre + 'PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNzUiIGhlaWdodD0iMjc1Ij48L3N2Zz4%3D';
|
||||
|
||||
testImg = $(new Image()).attr({
|
||||
src: testSrc,
|
||||
width: 0,
|
||||
height: 0
|
||||
}).appendTo('body')
|
||||
.load(function () {
|
||||
// Safari 4 crashes, Opera and Chrome don't
|
||||
makeIcons(!isSafari);
|
||||
}).error(function () {
|
||||
makeIcons();
|
||||
});
|
||||
} else {
|
||||
setTimeout(function() {
|
||||
if(!icons_made) makeIcons();
|
||||
},500);
|
||||
}
|
||||
}
|
||||
|
||||
function makeIcons(toImage, fallback) {
|
||||
|
@ -290,9 +344,12 @@ $(function() {
|
|||
var id = elem.getAttribute('id');
|
||||
if(id == 'svg_eof') return;
|
||||
holder = $('#' + id);
|
||||
|
||||
var svg = elem.getElementsByTagNameNS(svgns, 'svg')[0];
|
||||
var svgroot = svgdoc.createElementNS(svgns, "svg");
|
||||
if(elem.getElementsByTagNameNS) {
|
||||
var svg = elem.getElementsByTagNameNS(svgns, 'svg')[0];
|
||||
} else {
|
||||
var svg = elem.getElementsByTagName('svg')[0];
|
||||
}
|
||||
var svgroot = document.createElementNS(svgns, "svg");
|
||||
svgroot.setAttributeNS(svgns, 'viewBox', [0,0,icon_w,icon_h].join(' '));
|
||||
|
||||
// Make flexible by converting width/height to viewBox
|
||||
|
@ -318,7 +375,13 @@ $(function() {
|
|||
// With cloning, causes issue in Opera/Win/Non-EN
|
||||
if(!isOpera) svg = svg.cloneNode(true);
|
||||
|
||||
svgroot.appendChild(svg);
|
||||
// TODO: Figure out why makeSVG is necessary for IE9
|
||||
try {
|
||||
svgroot.appendChild(svg);
|
||||
} catch(e) {
|
||||
// For IE9
|
||||
svgroot.appendChild(makeSVG(svg));
|
||||
}
|
||||
|
||||
if(toImage) {
|
||||
// Without cloning, Safari will crash
|
||||
|
@ -339,8 +402,12 @@ $(function() {
|
|||
$.each(opts.placement, function(sel, id) {
|
||||
if(!svg_icons[id]) return;
|
||||
$(sel).each(function(i) {
|
||||
var copy = svg_icons[id].clone();
|
||||
if(i > 0 && !toImage) copy = fixIDs(copy, i, true);
|
||||
// TODO: Figure out why makeSVG is necessary for IE9
|
||||
try {
|
||||
var copy = svg_icons[id].clone();
|
||||
} catch(e) {
|
||||
var copy = makeSVG(svg_icons[id][0]);
|
||||
}
|
||||
setIcon($(this), copy, id);
|
||||
})
|
||||
});
|
||||
|
@ -348,18 +415,16 @@ $(function() {
|
|||
if(!fallback) {
|
||||
if(toImage) temp_holder.remove();
|
||||
if(data_el) data_el.remove();
|
||||
testImg.remove();
|
||||
if(testImg) testImg.remove();
|
||||
}
|
||||
|
||||
if(opts.resize) $.resizeSvgIcons(opts.resize);
|
||||
|
||||
icons_made = true;
|
||||
|
||||
if(opts.callback) opts.callback(svg_icons);
|
||||
|
||||
}
|
||||
|
||||
function fixIDs(svg_el, svg_num, force) {
|
||||
fixIDs = function(svg_el, svg_num, force) {
|
||||
var defs = svg_el.find('defs');
|
||||
if(!defs.length) return svg_el;
|
||||
|
||||
|
@ -433,7 +498,13 @@ $(function() {
|
|||
}
|
||||
}
|
||||
|
||||
$.getSvgIcon = function(id) { return svg_icons[id]; }
|
||||
$.getSvgIcon = function(id, uniqueClone) {
|
||||
var icon = svg_icons[id];
|
||||
if(uniqueClone) {
|
||||
icon = fixIDs(icon, 0, true).clone(true);
|
||||
}
|
||||
return icon;
|
||||
}
|
||||
|
||||
$.resizeSvgIcons = function(obj) {
|
||||
// FF2 and older don't detect .svg_icon, so we change it detect svg elems instead
|
||||
|
|
|
@ -87,7 +87,7 @@
|
|||
curseg = seglist.getItem(1);
|
||||
equal(curseg.pathSegTypeAsLetter, "L", "Before conversion, segment #2 type");
|
||||
curseg = seglist.getItem(2);
|
||||
equal(curseg.pathSegType, 1, "Before conversion, segment #3 type");
|
||||
equal(curseg.pathSegTypeAsLetter, "Z", "Before conversion, segment #3 type" + d_abs);
|
||||
|
||||
// convert and verify segments
|
||||
var d = convert(p1, true);
|
||||
|
|
Loading…
Reference in a new issue