Correctly implement transform: matrix with 2d matrices (#53860)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53860

Fixes https://github.com/facebook/react-native/issues/53639

I've realized that our docs and validation logic states that we do support
3x3 matrixes (for 2d transforms). However they're not properly processed
as the values are just copied into a 4x4 matrix.

This can be verified by applying the 3x3 identity matrix on any transform.

I'm fixing it by correctly populating the 4x4 matrix getting the values from the 3x3 matrix in input.

Changelog:
[General] [Fixed] - 9-element (2d) transform matrix are not correctly working

Reviewed By: christophpurrer

Differential Revision: D82836192

fbshipit-source-id: 12029b37ffd8375fff48ea7f9386b849dfe96a62
This commit is contained in:
Nicola Corti
2025-09-22 03:28:31 -07:00
committed by Facebook GitHub Bot
parent 23b2b99c4b
commit ce243df972
2 changed files with 62 additions and 2 deletions
@@ -614,8 +614,34 @@ inline void fromRawValue(
}
size_t i = 0;
for (auto number : numbers) {
transformMatrix.matrix[i++] = number;
if (numbers.size() == 16) {
for (auto number : numbers) {
transformMatrix.matrix[i++] = number;
}
} else if (numbers.size() == 9) {
// We need to convert the 2d transform matrix into a 3d one as such:
// [
// x01, x02, 0, x03
// x10, x11, 0, x12
// 0, 0, 1, 0
// x20, x21, 0, x22
// ]
transformMatrix.matrix[0] = numbers[0];
transformMatrix.matrix[1] = numbers[1];
transformMatrix.matrix[2] = 0;
transformMatrix.matrix[3] = numbers[2];
transformMatrix.matrix[4] = numbers[3];
transformMatrix.matrix[5] = numbers[4];
transformMatrix.matrix[6] = 0;
transformMatrix.matrix[7] = numbers[5];
transformMatrix.matrix[8] = 0;
transformMatrix.matrix[9] = 0;
transformMatrix.matrix[10] = 1;
transformMatrix.matrix[11] = 0;
transformMatrix.matrix[12] = numbers[6];
transformMatrix.matrix[13] = numbers[7];
transformMatrix.matrix[14] = 0;
transformMatrix.matrix[15] = numbers[8];
}
transformMatrix.operations.push_back(TransformOperation{
TransformOperationType::Arbitrary, Zero, Zero, Zero});
@@ -144,6 +144,13 @@ function TranslatePercentage() {
return <View style={styles.translatePercentageView} />;
}
function TranslateMatrix2D() {
return <View style={styles.translateMatrix2D} />;
}
function TranslateMatrix3D() {
return <View style={styles.translateMatrix3D} />;
}
const styles = StyleSheet.create({
container: {
height: 500,
@@ -288,6 +295,18 @@ const styles = StyleSheet.create({
alignSelf: 'flex-start',
backgroundColor: 'lightblue',
},
translateMatrix2D: {
transform: [{matrix: [1, 0, 0, 0, 1, 0, 0, 0, 1]}],
width: 50,
height: 50,
backgroundColor: 'red',
},
translateMatrix3D: {
transform: [{matrix: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]}],
height: 50,
width: 50,
backgroundColor: 'green',
},
});
exports.title = 'Transforms';
@@ -414,4 +433,19 @@ exports.examples = [
return <TranslatePercentage />;
},
},
{
title: 'Transform Matrix 2D',
description: "transform: 'matrix(1, 0, 0, 0, 1, 0, 0, 0, 1)'",
render(): React.Node {
return <TranslateMatrix2D />;
},
},
{
title: 'Transform Matrix 3D',
description:
"transform: 'matrix(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)'",
render(): React.Node {
return <TranslateMatrix3D />;
},
},
] as Array<RNTesterModuleExample>;