From 6e6d4b9d0f38699c6c42b4bfc7873570a3bba48b Mon Sep 17 00:00:00 2001 From: Hin-Tak Leung Date: Thu, 5 Jun 2025 23:59:59 +0100 Subject: [PATCH 1/3] M44 constructors and methods Part of #338 Conflicts: src/skia/Matrix.cpp --- src/skia/Matrix.cpp | 50 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/skia/Matrix.cpp b/src/skia/Matrix.cpp index a0eb9128a..1cda8d57f 100644 --- a/src/skia/Matrix.cpp +++ b/src/skia/Matrix.cpp @@ -1810,6 +1810,56 @@ py::class_(m, "M44", R"docstring( down +Z goes into the screen (away from the viewer) )docstring") .def(py::init<>()) + .def(py::init(), py::arg("src")) + .def(py::init(), py::arg("a"), py::arg("b")) + .def_static("Rows", &SkM44::Rows, + py::arg("r0"), py::arg("r1"), py::arg("r2"), py::arg("r3")) + .def_static("Cols", &SkM44::Cols, + py::arg("c0"), py::arg("c1"), py::arg("c2"), py::arg("c3")) + .def_static("RowMajor", &SkM44::RowMajor, py::arg("r")) + .def_static("ColMajor", &SkM44::ColMajor, py::arg("c")) + .def_static("Translate", &SkM44::Translate, + py::arg("x"), py::arg("y"), py::arg("z") = 0) + .def_static("Scale", &SkM44::Scale, + py::arg("x"), py::arg("y"), py::arg("z") = 1) + .def_static("Rotate", &SkM44::Rotate, + py::arg("axis"), py::arg("radians")) + .def_static("RectToRect", &SkM44::RectToRect, + py::arg("src"), py::arg("dst")) + .def_static("LookAt", &SkM44::LookAt, + py::arg("eye"), py::arg("center"), py::arg("up")) + .def_static("Perspective", &SkM44::Perspective, + py::arg("near"), py::arg("far"), py::arg("angle")) + .def("setIdentity", &SkM44::setIdentity) + .def("setTranslate", &SkM44::setTranslate, + py::arg("x"), py::arg("y"), py::arg("z") = 0) + .def("setScale", &SkM44::setScale, + py::arg("x"), py::arg("y"), py::arg("z") = 1) + .def("setRotateUnitSinCos", &SkM44::setRotateUnitSinCos, + py::arg("axis"), py::arg("sinAngle"), py::arg("cosAngle")) + .def("setRotateUnit", &SkM44::setRotateUnit, + py::arg("axis"), py::arg("radians")) + .def("setRotate", &SkM44::setRotate, + py::arg("axis"), py::arg("radians")) + .def("setConcat", &SkM44::setConcat, + py::arg("a"), py::arg("b")) + .def("preConcat", py::overload_cast(&SkM44::preConcat), + py::arg("m")) + .def("postConcat", &SkM44::postConcat, + py::arg("m")) + .def("normalizePerspective", &SkM44::normalizePerspective) + .def("isFinite", &SkM44::isFinite) + .def("asM33", &SkM44::asM33) + .def("preTranslate", &SkM44::preTranslate, + py::arg("x"), py::arg("y"), py::arg("z") = 0) + .def("postTranslate", &SkM44::postTranslate, + py::arg("x"), py::arg("y"), py::arg("z") = 0) + .def("preScale", py::overload_cast(&SkM44::preScale), + py::arg("x"), py::arg("y")) + .def("preScale", py::overload_cast(&SkM44::preScale), + py::arg("x"), py::arg("y"), py::arg("z")) + .def("preConcat", py::overload_cast(&SkM44::preConcat), + py::arg("m")) ; // RSXform From 7338f0466bad582ab901bd907c75d6473c4a3a8c Mon Sep 17 00:00:00 2001 From: Hin-Tak Leung Date: Fri, 6 Jun 2025 23:56:09 +0100 Subject: [PATCH 2/3] SkM44::rc and SkM44::setRC, single element getter/setter with bound check --- src/skia/Matrix.cpp | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/skia/Matrix.cpp b/src/skia/Matrix.cpp index 1cda8d57f..036fa3c64 100644 --- a/src/skia/Matrix.cpp +++ b/src/skia/Matrix.cpp @@ -1830,6 +1830,34 @@ py::class_(m, "M44", R"docstring( py::arg("eye"), py::arg("center"), py::arg("up")) .def_static("Perspective", &SkM44::Perspective, py::arg("near"), py::arg("far"), py::arg("angle")) + .def("rc", + [] (const SkM44& self, int r, int c) { + if ((r < 0) || (r > 3) || (c < 0) || (c > 3)) + throw py::value_error("Indices must be between 0 to 3."); + return self.rc(r, c); + }, + R"docstring( + Returns one matrix value from a particular row/column. + + :param r: matrix row to fetch + :param c: matrix column to fetch + :return: value at the given matrix position + )docstring", + py::arg("r"), py::arg("c")) + .def("setRC", + [] (SkM44& self, int r, int c, SkScalar value) { + if ((r < 0) || (r > 3) || (c < 0) || (c > 3)) + throw py::value_error("Indices must be between 0 to 3."); + self.setRC(r, c, value); + }, + R"docstring( + Set one matrix value at a particular row/column. + + :param r: matrix row to set + :param c: matrix column to set + :param value: value to set + )docstring", + py::arg("r"), py::arg("c"), py::arg("value")) .def("setIdentity", &SkM44::setIdentity) .def("setTranslate", &SkM44::setTranslate, py::arg("x"), py::arg("y"), py::arg("z") = 0) From 6d6bd1f57525265f665b4ad0e4303a72fed1062a Mon Sep 17 00:00:00 2001 From: Hin-Tak Leung Date: Sat, 7 Jun 2025 00:30:01 +0100 Subject: [PATCH 3/3] Two set/get tests on m44 --- tests/test_matrix.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/test_matrix.py b/tests/test_matrix.py index 7bd545103..f9492575d 100644 --- a/tests/test_matrix.py +++ b/tests/test_matrix.py @@ -433,3 +433,24 @@ def test_Matrix_InvalidMatrix(): def test_Matrix_Concat(matrix): assert isinstance(skia.Matrix.Concat(matrix, matrix), skia.Matrix) + + +@pytest.fixture +def m44(): + return skia.M44() + + +def test_m44_set_outofbound(m44): + try: + outofbound = m44.rc(4,0) + raise RuntimeError('Not reachable - Out of Bound is expected, so you should not see this!') + except ValueError: + # expected. + pass + + +def test_m44_set_and_get(m44): + oldvalue = m44.rc(3,2) + m44.setRC(3,2, 100) + assert m44.rc(3,2) == 100 + m44.setRC(3,2, oldvalue)