snap.js/src/equal.js

172 lines
5.7 KiB
JavaScript

// Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
Snap.plugin(function (Snap, Element, Paper, glob) {
var names = {},
reUnit = /[a-z]+$/i,
Str = String;
names.stroke = names.fill = "colour";
function getEmpty(item) {
var l = item[0];
switch (l.toLowerCase()) {
case "t": return [l, 0, 0];
case "m": return [l, 1, 0, 0, 1, 0, 0];
case "r": if (item.length == 4) {
return [l, 0, item[2], item[3]];
} else {
return [l, 0];
}
case "s": if (item.length == 5) {
return [l, 1, 1, item[3], item[4]];
} else if (item.length == 3) {
return [l, 1, 1];
} else {
return [l, 1];
}
}
}
function equaliseTransform(t1, t2, getBBox) {
t2 = Str(t2).replace(/\.{3}|\u2026/g, t1);
t1 = Snap.parseTransformString(t1) || [];
t2 = Snap.parseTransformString(t2) || [];
var maxlength = Math.max(t1.length, t2.length),
from = [],
to = [],
i = 0, j, jj,
tt1, tt2;
for (; i < maxlength; i++) {
tt1 = t1[i] || getEmpty(t2[i]);
tt2 = t2[i] || getEmpty(tt1);
if ((tt1[0] != tt2[0]) ||
(tt1[0].toLowerCase() == "r" && (tt1[2] != tt2[2] || tt1[3] != tt2[3])) ||
(tt1[0].toLowerCase() == "s" && (tt1[3] != tt2[3] || tt1[4] != tt2[4]))
) {
t1 = Snap._.transform2matrix(t1, getBBox());
t2 = Snap._.transform2matrix(t2, getBBox());
from = [["m", t1.a, t1.b, t1.c, t1.d, t1.e, t1.f]];
to = [["m", t2.a, t2.b, t2.c, t2.d, t2.e, t2.f]];
break;
}
from[i] = [];
to[i] = [];
for (j = 0, jj = Math.max(tt1.length, tt2.length); j < jj; j++) {
j in tt1 && (from[i][j] = tt1[j]);
j in tt2 && (to[i][j] = tt2[j]);
}
}
return {
from: path2array(from),
to: path2array(to),
f: getPath(from)
};
}
function getNumber(val) {
return val;
}
function getUnit(unit) {
return function (val) {
return +val.toFixed(3) + unit;
};
}
function getColour(clr) {
return Snap.rgb(clr[0], clr[1], clr[2]);
}
function getPath(path) {
var k = 0, i, ii, j, jj, out, a, b = [];
for (i = 0, ii = path.length; i < ii; i++) {
out = "[";
a = ['"' + path[i][0] + '"'];
for (j = 1, jj = path[i].length; j < jj; j++) {
a[j] = "val[" + (k++) + "]";
}
out += a + "]";
b[i] = out;
}
return Function("val", "return Snap.path.toString.call([" + b + "])");
}
function path2array(path) {
var out = [];
for (var i = 0, ii = path.length; i < ii; i++) {
for (var j = 1, jj = path[i].length; j < jj; j++) {
out.push(path[i][j]);
}
}
return out;
}
Element.prototype.equal = function (name, b) {
return eve("snap.util.equal", this, name, b).firstDefined();
};
eve.on("snap.util.equal", function (name, b) {
var A, B, a = Str(this.attr(name) || ""),
el = this;
if (a == +a && b == +b) {
return {
from: +a,
to: +b,
f: getNumber
};
}
if (names[name] == "colour") {
A = Snap.color(a);
B = Snap.color(b);
return {
from: [A.r, A.g, A.b, A.opacity],
to: [B.r, B.g, B.b, B.opacity],
f: getColour
};
}
if (name == "transform" || name == "gradientTransform" || name == "patternTransform") {
if (b instanceof Snap.Matrix) {
b = b.toTransformString();
}
if (!Snap._.rgTransform.test(b)) {
b = Snap._.svgTransform2string(b);
}
return equaliseTransform(a, b, function () {
return el.getBBox(1);
});
}
if (name == "d" || name == "path") {
A = Snap.path.toCubic(a, b);
return {
from: path2array(A[0]),
to: path2array(A[1]),
f: getPath(A[0])
};
}
if (name == "points") {
A = Str(a).split(Snap._.separator);
B = Str(b).split(Snap._.separator);
return {
from: A,
to: B,
f: function (val) { return val; }
};
}
aUnit = a.match(reUnit);
var bUnit = Str(b).match(reUnit);
if (aUnit && aUnit == bUnit) {
return {
from: parseFloat(a),
to: parseFloat(b),
f: getUnit(aUnit)
};
} else {
return {
from: this.asPX(name),
to: this.asPX(name, b),
f: getNumber
};
}
});
});