snapsvg/src/equal.js

224 lines
5.3 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.
import eve from './eve.js'
import { Snap } from './svg.js'
import { is } from './utils.js'
import { SEPARATOR } from './lib/constants.js'
import { parseColor } from './lib/color.js'
import { Matrix } from './matrix.js'
let names = {},
reUnit = /[%a-z]+$/i,
Str = String
names.stroke = names.fill = 'colour'
function getEmpty(item) {
let 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) {
t1 = t1 || new Matrix()
t2 = t2 || new Matrix()
t1 = Snap.parseTransformString(t1.toTransformString()) || []
t2 = Snap.parseTransformString(t2.toTransformString()) || []
let 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 getViewBox(val) {
return val.join(' ')
}
function getColour(clr) {
return Snap.rgb(clr[0], clr[1], clr[2], clr[3])
}
function getPath(path) {
let 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) {
let out = []
for (let i = 0, ii = path.length; i < ii; i++) {
for (let j = 1, jj = path[i].length; j < jj; j++) {
out.push(path[i][j])
}
}
return out
}
function isNumeric(obj) {
return isFinite(obj)
}
function arrayEqual(arr1, arr2) {
if (!is(arr1, 'array') || !is(arr2, 'array')) {
return false
}
return arr1.toString() == arr2.toString()
}
eve.on('snap.util.equal', function (name, b) {
let A,
B,
a = Str(this.attr(name) || ''),
el = this
if (names[name] == 'colour') {
A = parseColor(a)
B = parseColor(b)
return {
from: [A.r, A.g, A.b, A.opacity],
to: [B.r, B.g, B.b, B.opacity],
f: getColour
}
}
if (name == 'viewBox') {
A = this.attr(name).vb.split(' ').map(Number)
B = b.split(' ').map(Number)
return {
from: A,
to: B,
f: getViewBox
}
}
if (
name == 'transform' ||
name == 'gradientTransform' ||
name == 'patternTransform'
) {
if (typeof b == 'string') {
b = Str(b).replace(/\.{3}|\u2026/g, a)
}
a = this.matrix
if (!Snap._.rgTransform.test(b)) {
b = Snap._.transform2matrix(Snap._.svgTransform2string(b), this.getBBox())
} else {
b = Snap._.transform2matrix(b, this.getBBox())
}
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(SEPARATOR)
B = Str(b).split(SEPARATOR)
return {
from: A,
to: B,
f: function (val) {
return val
}
}
}
if (isNumeric(a) && isNumeric(b)) {
return {
from: parseFloat(a),
to: parseFloat(b),
f: getNumber
}
}
let aUnit = a.match(reUnit),
bUnit = Str(b).match(reUnit)
if (aUnit && arrayEqual(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
}
}
})
JavaScript 100%