delete this.start;
};
// path utilities
- var pathMethods = {
- absolutely: function () {
- this.isAbsolute = true;
- return this;
- },
- relatively: function () {
- this.isAbsolute = false;
- return this;
- },
- moveTo: function (x, y) {
- var d = this.isAbsolute ? "M" : "m";
- d += +parseFloat(x).toFixed(3) + " " + (+parseFloat(y).toFixed(3)) + " ";
- this.attr({path: this.attrs.path + d});
- return this;
- },
- lineTo: function (x, y) {
- var d = this.isAbsolute ? "L" : "l";
- d += +parseFloat(x).toFixed(3) + " " + (+parseFloat(y).toFixed(3)) + " ";
- this.attr({path: this.attrs.path + d});
- return this;
- },
- arcTo: function (rx, ry, large_arc_flag, sweep_flag, x, y) {
- var d = this.isAbsolute ? "A" : "a";
- d += [+parseFloat(rx).toFixed(3), +parseFloat(ry).toFixed(3), 0, large_arc_flag, sweep_flag, +parseFloat(x).toFixed(3), +parseFloat(y).toFixed(3)].join(" ");
- this.attr({path: this.attrs.path + d});
- return this;
- },
- curveTo: function () {
- var args = Array.prototype.splice.call(arguments, 0, arguments.length),
- d = [0, 0, 0, 0, "s", 0, "c"][args.length] || "";
- if (this.isAbsolute) {
- d = d.toUpperCase();
- }
- this.attr({path: this.attrs.path + d + args});
- return this;
- },
- qcurveTo: function () {
- var d = [0, 1, "t", 3, "q"][arguments.length],
- args = Array.prototype.splice.call(arguments, 0, arguments.length);
- if (this.isAbsolute) {
- d = d.toUpperCase();
- }
- this.attr({path: this.attrs.path + d + args});
- return this;
- },
- addRoundedCorner: function (r, dir) {
- var rollback = this.isAbsolute,
- o = this;
- if (rollback) {
- this.relatively();
- rollback = function () {
- o.absolutely();
- };
- } else {
- rollback = function () {};
- }
- this.arcTo(r, r, 0, {"lu": 1, "rd": 1, "ur": 1, "dl": 1}[dir] || 0, r * (!!(dir.indexOf("r") + 1) * 2 - 1), r * (!!(dir.indexOf("d") + 1) * 2 - 1));
- rollback();
- return this;
- },
- andClose: function () {
- this.attr({path: this.attrs.path + "z"});
- return this;
- },
- getPathArray: function () {
- return R.parsePathString(this.attrs.path);
- }
- };
- var pathcache = {},
+ var pathcache = {"": []},
path2string = function () {
- var res = "";
+ var res = "",
+ item;
for (var i = 0, ii = this.length; i < ii; i++) {
- res += this[i][0] + this[i].join(",").substring(2);
+ for (var j = 0, jj = this[i].length; j < jj; j++) {
+ item = this[i][j];
+ res += isNaN(item) ? item : +item.toFixed(3);
+ j && j != jj - 1 && (res += ",");
+ }
+ i != ii - 1 && (res += "\n");
}
return res.replace(/,(?=-)/g, "");
},
});
data.toString = path2string;
}
- if (pathcount.length > 20) {
+ if (pathcount.length > 200) {
delete pathcache[pathcount.unshift()];
}
pathcount.push(pathString);
return data;
};
var pathDimensions = function (path) {
- var pathArray = path;
- pathArray = pathToAbsolute(pathArray);
- var x = [],
- y = [],
- length = 0;
- for (var i = 0, ii = pathArray.length; i < ii; i++) {
- var pa = pathArray[i];
- switch (pa[0]) {
- case "Z":
- break;
- case "A":
- x.push(pa[pa.length - 2]);
- y.push(pa[pa.length - 1]);
- break;
- default:
- for (var j = 1, jj = pa.length; j < jj; j++) {
- (j % 2 ? x : y).push(pa[j]);
- }
+ pathDimensions.cache = pathDimensions.cache || {};
+ pathDimensions.count = pathDimensions.count || [];
+ if (path in pathDimensions.cache) {
+ return pathDimensions.cache[path];
+ }
+ path = path2curve(path);
+ var x = 0,
+ y = 0,
+ X = [],
+ Y = [];
+ for (var i = 0, ii = path.length; i < ii; i++) {
+ if (path[i][0] == "M") {
+ x = path[i][1];
+ y = path[i][2];
+ } else {
+ var dim = curveDim(x, y, path[i][1], path[i][2], path[i][3], path[i][4], path[i][5], path[i][6]);
+ X = X.concat(dim.min.x, dim.max.x);
+ Y = Y.concat(dim.min.y, dim.max.y);
}
}
- var minx = Math.min.apply(Math, x),
- miny = Math.min.apply(Math, y);
- if (!x.length) {
- return {
- x: 0,
- y: 0,
- width: 0,
- height: 0,
- X: 0,
- Y: 0
- };
- } else {
- return {
- x: minx,
- y: miny,
- width: Math.max.apply(Math, x) - minx,
- height: Math.max.apply(Math, y) - miny,
- X: x,
- Y: y
- };
+ var xmin = Math.min.apply(0, X),
+ ymin = Math.min.apply(0, Y);
+ if (pathDimensions.count.length > 100) {
+ delete pathDimensions.cache[pathDimensions.count.unshift()];
}
+ pathDimensions.count.push(path);
+ return (pathDimensions.cache[path] = {
+ x: xmin,
+ y: ymin,
+ width: Math.max.apply(0, X) - xmin,
+ height: Math.max.apply(0, Y) - ymin
+ });
},
pathToRelative = function (pathArray) {
+ if (typeof pathArray == "string") {
+ pathArray = R.parsePathString(pathArray);
+ }
+ pathToRelative.cache = pathToRelative.cache || {};
+ pathToRelative.count = pathToRelative.count || [];
+ if (pathArray in pathToRelative.cache) {
+ return pathClone(pathToRelative.cache[pathArray]);
+ }
var res = [],
x = 0,
y = 0,
+ mx = 0,
+ my = 0,
start = 0;
- if (typeof pathArray == "string") {
- pathArray = R.parsePathString(pathArray);
- }
if (pathArray[0][0] == "M") {
x = pathArray[0][1];
y = pathArray[0][2];
+ mx = x;
+ my = y;
start++;
res.push(["M", x, y]);
}
case "v":
r[1] = +(pa[1] - y).toFixed(3);
break;
+ case "m":
+ mx = pa[1];
+ my = pa[2];
default:
for (var j = 1, jj = pa.length; j < jj; j++) {
r[j] = +(pa[j] - ((j % 2) ? x : y)).toFixed(3);
}
} else {
r = res[i] = [];
+ if (pa[0] == "m") {
+ mx = pa[1] + x;
+ my = pa[2] + y;
+ }
for (var k = 0, kk = pa.length; k < kk; k++) {
res[i][k] = pa[k];
}
var len = res[i].length;
switch (res[i][0]) {
case "z":
+ x = mx;
+ y = my;
break;
case "h":
x += +res[i][len - 1];
y += +res[i][len - 1];
}
}
- res.toString = pathArray.toString;
+ res.toString = path2string;
+ if (pathToRelative.count.length > 100) {
+ delete pathToRelative.cache[pathToRelative.count.unshift()];
+ }
+ pathToRelative.count.push(pathArray);
+ return pathClone(pathToRelative.cache[pathArray] = res);
+ },
+ pathClone = function (pathArray) {
+ var res = [];
+ if (typeof pathArray == "string") {
+ pathArray = R.parsePathString(pathArray);
+ }
+ for (var i = 0, ii = pathArray.length; i < ii; i++) {
+ res[i] = [];
+ for (var j = 0, jj = pathArray[i].length; j < jj; j++) {
+ res[i][j] = pathArray[i][j];
+ }
+ }
+ res.toString = path2string;
return res;
},
pathToAbsolute = function (pathArray) {
+ if (typeof pathArray == "string") {
+ pathArray = R.parsePathString(pathArray);
+ }
+ pathToAbsolute.cache = pathToAbsolute.cache || {};
+ pathToAbsolute.count = pathToAbsolute.count || [];
+ if (pathArray in pathToAbsolute.cache) {
+ return pathClone(pathToAbsolute.cache[pathArray]);
+ }
var res = [],
x = 0,
y = 0,
+ mx = 0,
+ my = 0,
start = 0;
- if (typeof pathArray == "string") {
- pathArray = R.parsePathString(pathArray);
- }
if (pathArray[0][0] == "M") {
x = +pathArray[0][1];
y = +pathArray[0][2];
+ mx = x;
+ my = y;
start++;
res[0] = ["M", x, y];
}
case "A":
r[1] = pa[1];
r[2] = pa[2];
- r[3] = 0;
+ r[3] = pa[3];
r[4] = pa[4];
r[5] = pa[5];
- r[6] = +(pa[6] + x).toFixed(3);
- r[7] = +(pa[7] + y).toFixed(3);
+ r[6] = +(pa[6] + x);
+ r[7] = +(pa[7] + y);
break;
case "V":
r[1] = +pa[1] + y;
case "H":
r[1] = +pa[1] + x;
break;
+ case "M":
+ mx = +pa[1] + x;
+ my = +pa[2] + y;
default:
for (var j = 1, jj = pa.length; j < jj; j++) {
r[j] = +pa[j] + ((j % 2) ? x : y);
}
switch (r[0]) {
case "Z":
+ x = mx;
+ y = my;
break;
case "H":
x = r[1];
y = res[i][res[i].length - 1];
}
}
- res.toString = pathArray.toString;
- return res;
+ res.toString = path2string;
+ if (pathToAbsolute.count.length > 100) {
+ delete pathToAbsolute.cache[pathToAbsolute.count.unshift()];
+ }
+ pathToAbsolute.count.push(pathArray);
+ return pathClone(pathToAbsolute.cache[pathArray] = res);
},
l2c = function (x1, y1, x2, y2) {
return [x1, y1, x2, y2, x2, y2];
cy = (1 - t) * c2y + t * p2y;
return {x: x, y: y, m: {x: mx, y: my}, n: {x: nx, y: ny}, start: {x: ax, y: ay}, end: {x: cx, y: cy}};
},
+ curveDim = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {
+ var a = (c2x - 2 * c1x + p1x) - (p2x - 2 * c2x + c1x),
+ b = 2 * (c1x - p1x) - 2 * (c2x - c1x),
+ c = p1x - c1x,
+ t1 = (-b + Math.sqrt(b * b - 4 * a * c)) / 2 / a,
+ t2 = (-b - Math.sqrt(b * b - 4 * a * c)) / 2 / a,
+ y = [p1y, p2y],
+ x = [p1x, p2x],
+ dot1 = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1 > 0 && t1 < 1 ? t1 : 0),
+ dot2 = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2 > 0 && t2 < 1 ? t2 : 0);
+ x = x.concat(dot1.x, dot2.x);
+ y = y.concat(dot1.y, dot2.y);
+ a = (c2y - 2 * c1y + p1y) - (p2y - 2 * c2y + c1y);
+ b = 2 * (c1y - p1y) - 2 * (c2y - c1y);
+ c = p1y - c1y;
+ t1 = (-b + Math.sqrt(b * b - 4 * a * c)) / 2 / a;
+ t2 = (-b - Math.sqrt(b * b - 4 * a * c)) / 2 / a;
+ dot1 = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1 > 0 && t1 < 1 ? t1 : 0);
+ dot2 = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2 > 0 && t2 < 1 ? t2 : 0);
+ x = x.concat(dot1.x, dot2.x);
+ y = y.concat(dot1.y, dot2.y);
+ return {
+ min: {x: Math.min.apply(Math, x), y: Math.min.apply(Math, y)},
+ max: {x: Math.max.apply(Math, x), y: Math.max.apply(Math, y)}
+ };
+ },
path2curve = function (path, path2) {
path2curve.cache = path2curve.cache || {};
path2curve.count = path2curve.count || [];
- if (path in path2curve.cache) {
+ if ((path + "&" + path2) in path2curve.cache) {
return path2curve.cache[path + "&" + path2];
}
var p = pathToAbsolute(path),
R.toString = function () {
return "Your browser supports SVG.\nYou are running Rapha\u00ebl " + this.version;
};
- var thePath = function (params, pathString, SVG) {
+ var thePath = function (pathString, SVG) {
var el = doc.createElementNS(SVG.svgns, "path");
if (SVG.canvas) {
SVG.canvas.appendChild(el);
}
var p = new Element(el, SVG);
- p.isAbsolute = true;
- for (var method in pathMethods) {
- p[method] = pathMethods[method];
- }
p.type = "path";
- p.attrs.path = "" + (pathString || "");
- pathString && p.node.setAttribute("d", R.parsePathString(pathString));
- if (params) {
- !params.gradient && (params.fill = params.fill || "none");
- params.stroke = params.stroke || "#000";
- } else {
- params = {fill: "none", stroke: "#000"};
- }
- setFillAndStroke(p, params);
+ p.attrs.path = R.parsePathString(pathString);
+ pathString && p.node.setAttribute("d", p.attrs.path);
+ setFillAndStroke(p, {fill: "none", stroke: "#000"});
return p;
};
var addGradientFill = function (o, gradient, SVG) {
break;
case "path":
if (o.type == "path") {
- node.setAttribute("d", R.parsePathString(value));
+ attrs.path = R.parsePathString(value);
+ node.setAttribute("d", attrs.path);
}
case "width":
node.setAttribute(att, value);
this._ = {
tx: 0,
ty: 0,
- rt: {deg: 0, x: 0, y: 0},
+ rt: {deg: 0, cx: 0, cy: 0},
sx: 1,
sy: 1
};
cx = cx == null ? bbox.x + bbox.width / 2 : cx;
cy = cy == null ? bbox.y + bbox.height / 2 : cy;
if (this._.rt.deg) {
- this.transformations[0] = ("rotate(" + this._.rt.deg + " " + cx + " " + cy + ")");
+ this.transformations[0] = "rotate(".concat(this._.rt.deg, " ", cx, " ", cy, ")");
} else {
this.transformations[0] = "";
}
R.toString = function () {
return "Your browser doesn\u2019t support SVG. Assuming it is Internet Explorer and falling down to VML.\nYou are running Rapha\u00ebl " + this.version;
};
- var thePath = function (params, pathString, VML) {
+ var thePath = function (pathString, VML) {
var g = createNode("group"), gl = g.style;
gl.position = "absolute";
gl.left = 0;
ol.width = VML.width + "px";
ol.height = VML.height + "px";
el.path = "";
- if (params["class"]) {
- el.className = "rvml " + params["class"];
- }
el.coordsize = this.coordsize;
el.coordorigin = this.coordorigin;
g.appendChild(el);
p.isAbsolute = true;
p.type = "path";
p.path = [];
- p.last = {x: 0, y: 0, bx: 0, by: 0, isAbsolute: true};
+ // p.last = {x: 0, y: 0, bx: 0, by: 0, isAbsolute: true};
p.Path = "";
- for (var method in pathMethods) {
- p[method] = pathMethods[method];
- }
-
- if (params) {
- params.fill = params.fill || "none";
- params.stroke = params.stroke || "#000";
- } else {
- params = {fill: "none", stroke: "#000"};
- }
if (pathString) {
- p.node.path = path2vml(pathString);
- p.attrs.path = pathString;
- }
- setFillAndStroke(p, params);
- if (params.gradient) {
- addGradientFill(p, params.gradient);
+ p.attrs.path = R.parsePathString(pathString);
+ p.node.path = path2vml(p.attrs.path);
}
+ setFillAndStroke(p, {fill: "none", stroke: "#000"});
p.setBox();
VML.canvas.appendChild(g);
return p;
};
Element.prototype.getBBox = function () {
if (this.type == "path") {
- return pathDimensions(this.attr("path"));
+ return pathDimensions(this.attrs.path);
}
return {
x: this.X + (this.bbx || 0),
paper.ellipse = function (x, y, rx, ry) {
return theEllipse(this, x, y, rx, ry);
};
- paper.path = function (params, pathString) {
- if (typeof params == "string" && !pathString) {
- pathString = params;
- params = {};
- }
- params = params || {};
- return thePath(params, pathString, this);
+ paper.path = function (pathString) {
+ return thePath(pathString, this);
};
paper.image = function (src, x, y, w, h) {
return theImage(this, src, x, y, w, h);
paper.setSize = setSize;
Element.prototype.stop = function () {
clearTimeout(this.animation_in_progress);
+ return this;
};
Element.prototype.scale = function (x, y, cx, cy) {
if (x == null && y == null) {
var path = pathToRelative(this.attrs.path);
path[0][1] += +x;
path[0][2] += +y;
- this.attr({path: path.join(" ")});
+ this.attr({path: path});
break;
}
return this;
};
-
+
// Set
var Set = function (items) {
this.items = [];