Accumulation of transformations
UPDATE: I’ve heavily edited the following based on feedback from Dr. Hoffmann.
One implementation issue I discovered with regards to
<animateTransform> is how to accumulate repeated transformations.
Consider the following example:
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue">
<animateTransform attributeName="transform" attributeType="XML"
type="skewX" fill="freeze" from="0" to="22" dur="0.3s"
A skew operation produces a transformation matrix with one element set to tan(angle), so here it would be tan(22) at the end of the simple duration. After 3 repetitions, what would be the value of this element? If we just accumulate the animation parameters (i.e. angle=22), then we’d get tan(3 * 22), i.e. tan(66). However, if we accumulate using post-multiplication of matrices the answer is not tan(3 * 22) but 3 * tan(22).
In the graphic below the black outline represents the result if we just add up the animation parameters (i.e. skew by 66 degrees), whilst the red outline represents the result when we use matrix multiplication.
In my testing, in Opera 9.62 the arrow ends up inside the black outline whereas in Batik 1.7 it ends up inside the red outline.
So which is correct? SVG 1.1 says that for additive animation (
<animateTransform> we should post-multiply matrices.
However, is the addition used when performing additive animation the same as the addition used when accumulating repetitions? SMILANIM 3.3.1 seems to suggest some relationship between the two when it says:
[The cumulative attribute] is ignored if the target attribute value does not support addition
However, in the SVG Tiny 1.2 Test Suite a different view has been taken. See Dr. Hoffmann’s comments below for a proper explanation. My understanding is that different addition is to be used at different stages of the compositing.
When we are calculating cumulative values, SMIL3 gives us the formula:
fi(t) = (f(d) * i) + f(t - (i*d))
This simply operates on the animation parameters. So in the example at the beginning, it means tan(3 * 22). However, when we come to composite with underlying values in the animation sandwich, a different kind of addition is used. For this, SMIL3 gives the following formula:
F(t,u) = u + ff(t)
<animateTransform> we should use matrix post-multiplication, i.e. 3 * tan(22).