private static bool ComputeDecomposedTransform(TransformOperations operations, int startOffset, out Matrix.Decomposed decomposed) { Matrix transform = operations.ApplyTransforms(startOffset); if (!Matrix.TryDecomposeTransform(transform, out decomposed)) { return(false); } return(true); }
private static bool TryInterpolate(TransformOperations from, TransformOperations to, double progress, ref TransformOperations result) { bool fromIdentity = from.IsIdentity; bool toIdentity = to.IsIdentity; if (fromIdentity && toIdentity) { return(true); } int matchingPrefixLength = ComputeMatchingPrefixLength(from, to); int fromSize = fromIdentity ? 0 : from._operations.Count; int toSize = toIdentity ? 0 : to._operations.Count; int numOperations = Math.Max(fromSize, toSize); var builder = new Builder(matchingPrefixLength); for (int i = 0; i < matchingPrefixLength; i++) { TransformOperation interpolated = new TransformOperation { Type = TransformOperation.OperationType.Identity }; if (!TransformOperation.TryInterpolate( i >= fromSize ? default(TransformOperation?) : from._operations[i], i >= toSize ? default(TransformOperation?) : to._operations[i], progress, ref interpolated)) { return(false); } builder.Append(interpolated); } if (matchingPrefixLength < numOperations) { if (!ComputeDecomposedTransform(from, matchingPrefixLength, out Matrix.Decomposed fromDecomposed) || !ComputeDecomposedTransform(to, matchingPrefixLength, out Matrix.Decomposed toDecomposed)) { return(false); } var transform = InterpolationUtilities.InterpolateDecomposedTransforms(ref fromDecomposed, ref toDecomposed, progress); builder.AppendMatrix(InterpolationUtilities.ComposeTransform(transform)); } result = builder.Build(); return(true); }
public static TransformOperations Interpolate(TransformOperations from, TransformOperations to, double progress) { TransformOperations result = Identity; if (!TryInterpolate(from, to, progress, ref result)) { // If the matrices cannot be interpolated, fallback to discrete animation logic. // See https://drafts.csswg.org/css-transforms/#matrix-interpolation result = progress < 0.5 ? from : to; } return(result); }
private static int ComputeMatchingPrefixLength(TransformOperations from, TransformOperations to) { int numOperations = Math.Min(from._operations.Count, to._operations.Count); for (int i = 0; i < numOperations; i++) { if (from._operations[i].Type != to._operations[i].Type) { return(i); } } // If the operations match to the length of the shorter list, then pad its // length with the matching identity operations. // https://drafts.csswg.org/css-transforms/#transform-function-lists return(Math.Max(from._operations.Count, to._operations.Count)); }