/**
* @private
* @class Ext.draw.sprite.AnimationParser
*
* Computes an intermidiate value between two values of the same type for use in animations.
* Can have pre- and post- processor functions if the values need to be processed
* before an intermidiate value can be computed (parseInitial), or the computed value
* needs to be processed before it can be used as a valid attribute value (serve).
*/
Ext.define('Ext.draw.sprite.AnimationParser', function() {
function compute(from, to, delta) {
return from + (to - from) * delta;
}
return {
singleton: true,
attributeRe: /^url\(#([a-zA-Z-]+)\)$/,
requires: ['Ext.draw.Color'],
color: {
parseInitial: function(color1, color2) {
if (Ext.isString(color1)) {
color1 = Ext.util.Color.create(color1);
}
if (Ext.isString(color2)) {
color2 = Ext.util.Color.create(color2);
}
if ((color1 && color1.isColor) && (color2 && color2.isColor)) {
return [
[color1.r, color1.g, color1.b, color1.a],
[color2.r, color2.g, color2.b, color2.a]
];
}
else {
return [color1 || color2, color2 || color1];
}
},
compute: function(from, to, delta) {
if (!Ext.isArray(from) || !Ext.isArray(to)) {
return to || from;
}
else {
return [compute(from[0], to[0], delta), compute(from[1], to[1], delta),
compute(from[2], to[2], delta), compute(from[3], to[3], delta)];
}
},
serve: function(array) {
var color = Ext.util.Color.fly(array[0], array[1], array[2], array[3]);
return color.toString();
}
},
number: {
parse: function(n) {
return n === null ? null : +n;
},
compute: function(from, to, delta) {
if (!Ext.isNumber(from) || !Ext.isNumber(to)) {
return to || from;
}
else {
return compute(from, to, delta);
}
}
},
angle: {
parseInitial: function(from, to) {
if (to - from > Math.PI) {
to -= Math.PI * 2;
}
else if (to - from < -Math.PI) {
to += Math.PI * 2;
}
return [from, to];
},
compute: function(from, to, delta) {
if (!Ext.isNumber(from) || !Ext.isNumber(to)) {
return to || from;
}
else {
return compute(from, to, delta);
}
}
},
path: {
parseInitial: function(from, to) {
var fromStripes = from.toStripes(),
toStripes = to.toStripes(),
i, j,
fromLength = fromStripes.length,
toLength = toStripes.length,
fromStripe, toStripe,
length,
lastStripe = toStripes[toLength - 1],
endPoint = [lastStripe[lastStripe.length - 2],
lastStripe[lastStripe.length - 1]];
for (i = fromLength; i < toLength; i++) {
fromStripes.push(fromStripes[fromLength - 1].slice(0));
}
for (i = toLength; i < fromLength; i++) {
toStripes.push(endPoint.slice(0));
}
length = fromStripes.length;
toStripes.path = to;
toStripes.temp = new Ext.draw.Path();
for (i = 0; i < length; i++) {
fromStripe = fromStripes[i];
toStripe = toStripes[i];
fromLength = fromStripe.length;
toLength = toStripe.length;
toStripes.temp.commands.push('M');
for (j = toLength; j < fromLength; j += 6) {
toStripe.push(endPoint[0], endPoint[1], endPoint[0], endPoint[1],
endPoint[0], endPoint[1]);
}
lastStripe = toStripes[toStripes.length - 1];
endPoint = [lastStripe[lastStripe.length - 2],
lastStripe[lastStripe.length - 1]];
for (j = fromLength; j < toLength; j += 6) {
fromStripe.push(endPoint[0], endPoint[1], endPoint[0], endPoint[1],
endPoint[0], endPoint[1]);
}
for (i = 0; i < toStripe.length; i++) {
toStripe[i] -= fromStripe[i];
}
for (i = 2; i < toStripe.length; i += 6) {
toStripes.temp.commands.push('C');
}
}
return [fromStripes, toStripes];
},
compute: function(fromStripes, toStripes, delta) {
if (delta >= 1) {
return toStripes.path;
}
// eslint-disable-next-line vars-on-top
var i = 0,
ln = fromStripes.length,
j = 0,
ln2, from, to,
temp = toStripes.temp.params,
pos = 0;
for (; i < ln; i++) {
from = fromStripes[i];
to = toStripes[i];
ln2 = from.length;
for (j = 0; j < ln2; j++) {
temp[pos++] = to[j] * delta + from[j];
}
}
return toStripes.temp;
}
},
data: {
compute: function(from, to, delta, target) {
var iMaxFrom = from.length - 1,
iMaxTo = to.length - 1,
iMax = Math.max(iMaxFrom, iMaxTo),
i, start, end;
if (!target || target === from) {
target = [];
}
target.length = iMax + 1;
for (i = 0; i <= iMax; i++) {
start = from[Math.min(i, iMaxFrom)];
end = to[Math.min(i, iMaxTo)];
if (Ext.isNumber(start)) {
if (!Ext.isNumber(end)) {
// This may not give the desired visual result during
// animation (after all, we don't know what the target
// value should be, if it wasn't given to us), but it's
// better than spitting out a bunch of NaNs in the target
// array, when transitioning from a non-empty to an empty
// array.
end = 0;
}
target[i] = start + (end - start) * delta;
}
else {
target[i] = end;
}
}
return target;
}
},
text: {
compute: function(from, to, delta) {
return from.substr(0, Math.round(from.length * (1 - delta))) +
to.substr(Math.round(to.length * (1 - delta)));
}
},
limited: 'number',
limited01: 'number'
};
});