Bug 1018862 part 8 - Add special handling for non-invertible transforms; r=dholbert

This patch adjusts the tests for transform transitions that run on the
compositor to handle transitions that begin with a non-invertible transform.
In this case the first sample at the start of the animation won't create
a layer because in nsDisplayTransform::BuildLayer
/ FrameLayerBuilder::BuildContainerLayerFor we'll skip creating the layer once
we notice the equivalent matrix is singular.

In this patch we detect that case and force an extra sample betwee 0 and 200s at
100s. This means the layer will be created at t=100s and be available for
querying at the next sample.

Similar issues could occur, for example, if the transforms at both t=0s
and t=100s are not invertible but currently that doesn't occur. We can add
handling for that if and when it becomes necessary.
This commit is contained in:
Brian Birtles 2014-06-12 13:17:47 +09:00
Родитель d73c4f0840
Коммит da8fce7eea
2 изменённых файлов: 66 добавлений и 8 удалений

Просмотреть файл

@ -398,7 +398,7 @@ const ExpectComparisonTo = {
// "matrix3d(...)"
// [ 1, 0, 0, ... ]
// { a: 1, ty: 23 } etc.
function convertTo3dMatrix(matrixLike) {
window.convertTo3dMatrix = function(matrixLike) {
if (typeof(matrixLike) == "string") {
return convertStringTo3dMatrix(matrixLike);
} else if (Array.isArray(matrixLike)) {
@ -408,7 +408,13 @@ const ExpectComparisonTo = {
} else {
return null;
}
}
};
// In future most of these methods should be able to be replaced
// with DOMMatrix
window.isInvertible = function(matrix) {
return getDeterminant(matrix) != 0;
};
// Converts strings of the format "matrix(...)" and "matrix3d(...)" to a 3d
// matrix
@ -498,6 +504,37 @@ const ExpectComparisonTo = {
matrix[2][2] === 1 && matrix[2][3] === 0 &&
matrix[3][2] === 0 && matrix[3][3] === 1;
}
function getDeterminant(matrix) {
if (is2d(matrix)) {
return matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0];
}
return matrix[0][3] * matrix[1][2] * matrix[2][1] * matrix[3][0]
- matrix[0][2] * matrix[1][3] * matrix[2][1] * matrix[3][0]
- matrix[0][3] * matrix[1][1] * matrix[2][2] * matrix[3][0]
+ matrix[0][1] * matrix[1][3] * matrix[2][2] * matrix[3][0]
+ matrix[0][2] * matrix[1][1] * matrix[2][3] * matrix[3][0]
- matrix[0][1] * matrix[1][2] * matrix[2][3] * matrix[3][0]
- matrix[0][3] * matrix[1][2] * matrix[2][0] * matrix[3][1]
+ matrix[0][2] * matrix[1][3] * matrix[2][0] * matrix[3][1]
+ matrix[0][3] * matrix[1][0] * matrix[2][2] * matrix[3][1]
- matrix[0][0] * matrix[1][3] * matrix[2][2] * matrix[3][1]
- matrix[0][2] * matrix[1][0] * matrix[2][3] * matrix[3][1]
+ matrix[0][0] * matrix[1][2] * matrix[2][3] * matrix[3][1]
+ matrix[0][3] * matrix[1][1] * matrix[2][0] * matrix[3][2]
- matrix[0][1] * matrix[1][3] * matrix[2][0] * matrix[3][2]
- matrix[0][3] * matrix[1][0] * matrix[2][1] * matrix[3][2]
+ matrix[0][0] * matrix[1][3] * matrix[2][1] * matrix[3][2]
+ matrix[0][1] * matrix[1][0] * matrix[2][3] * matrix[3][2]
- matrix[0][0] * matrix[1][1] * matrix[2][3] * matrix[3][2]
- matrix[0][2] * matrix[1][1] * matrix[2][0] * matrix[3][3]
+ matrix[0][1] * matrix[1][2] * matrix[2][0] * matrix[3][3]
+ matrix[0][2] * matrix[1][0] * matrix[2][1] * matrix[3][3]
- matrix[0][0] * matrix[1][2] * matrix[2][1] * matrix[3][3]
- matrix[0][1] * matrix[1][0] * matrix[2][2] * matrix[3][3]
+ matrix[0][0] * matrix[1][1] * matrix[2][2] * matrix[3][3];
}
})();
//----------------------------------------------------------------------

Просмотреть файл

@ -1955,11 +1955,6 @@ function addAsyncTransformTests() {
}
function *runTransformTest(test) {
// Skip the following test for now.
// We'll work around this properly in a subsequent patch in this queue.
if (test.start == "skew(45deg, 45deg)")
return;
OMTAdiv.style.setProperty("transition-property", "none", "");
OMTAdiv.style.setProperty("transform", test.start, "");
OMTACs.getPropertyValue("transform");
@ -1968,7 +1963,17 @@ function *runTransformTest(test) {
OMTACs.getPropertyValue("transform");
yield waitForPaints();
winUtils.advanceTimeAndRefresh(200000);
// If the start value produced a non-invertible matrix the layer won't be
// created yet so we need to force an extra sample.
if (!isTransformInvertible(test.start)) {
winUtils.advanceTimeAndRefresh(100000);
yield waitForPaints();
winUtils.advanceTimeAndRefresh(100000);
yield waitForPaints();
} else {
winUtils.advanceTimeAndRefresh(200000);
yield waitForPaints();
}
omta_is_approx(OMTAdiv, "transform", OMTACs.getPropertyValue("transform"),
0.0001, RunningOn.Compositor,
@ -1997,6 +2002,22 @@ function addAsyncOpacityTest() {
OMTAdiv.style.removeProperty("transition");
});
}
function isTransformInvertible(transformStr) {
var computedStr = transformStrToComputedStr(transformStr);
if (!transformStr)
return false;
var matrix = convertTo3dMatrix(computedStr);
if (matrix === null)
return false;
return isInvertible(matrix);
}
function transformStrToComputedStr(transformStr) {
var div = document.createElement("div");
div.style.transform = transformStr;
return window.getComputedStyle(div).transform;
}
</script>
</pre>
</body>