[PATCH] add functional matrix-returning methods to Pycairo

  • Thread starter Lawrence D'Oliveiro
  • Start date
L

Lawrence D'Oliveiro

I find the matrix methods in Pycairo to be an annoying hodge-podge of
ones that overwrite the Matrix object in-place (init_rotate, invert)
versus ones that concatenate additional transformations (rotate, scale,
translate) versus ones that return new matrices without modifying
the originals (multiply).

Myself, I prefer methods that always return new matrices. This allows
for a more functional style of programming, e.g. given

m = cairo.Matrix()

then

m2 = m.translation(-10, -10) * m.rotation(math.pi / 4) * m.translation(10, 10)

concisely expresses rotation by 90° about the centre (10, 10).

Herewith a patch to add such methods to the cairo.Matrix class. Note
that the names (inverse, rotation, scaling, translation) are nouns,
to reflect the fact that they don't perform the actions, but they
return Matrix objects that do.

---
src/matrix.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 75 insertions(+), 0 deletions(-)

diff --git a/src/matrix.c b/src/matrix.c
index eefeab9..d1709b9 100644
--- a/src/matrix.c
+++ b/src/matrix.c
@@ -206,6 +206,76 @@ matrix_translate (PycairoMatrix *o, PyObject *args) {
}

static PyObject *
+matrix_translation(PycairoMatrix *unused, PyObject *args)
+ {
+ PyObject * result = NULL;
+ double tx, ty;
+ cairo_matrix_t result_matrix;
+ do /*once*/
+ {
+ if (!PyArg_ParseTuple(args, "dd:Matrix.translation", &tx, &ty))
+ break;
+ cairo_matrix_init_identity(&result_matrix);
+ cairo_matrix_translate(&result_matrix, tx, ty);
+ result = PycairoMatrix_FromMatrix(&result_matrix);
+ }
+ while (0);
+ return result;
+ } /*matrix_translation*/
+
+static PyObject *
+matrix_scaling(PycairoMatrix *unused, PyObject *args)
+ {
+ PyObject * result = NULL;
+ double sx, sy;
+ cairo_matrix_t result_matrix;
+ do /*once*/
+ {
+ if (!PyArg_ParseTuple(args, "dd:Matrix.scaling", &sx, &sy))
+ break;
+ cairo_matrix_init_identity(&result_matrix);
+ cairo_matrix_scale(&result_matrix, sx, sy);
+ result = PycairoMatrix_FromMatrix(&result_matrix);
+ }
+ while (0);
+ return result;
+ } /*matrix_scaling*/
+
+static PyObject *
+matrix_rotation(PycairoMatrix *unused, PyObject *args)
+ {
+ PyObject * result = NULL;
+ double radians;
+ cairo_matrix_t result_matrix;
+ do /*once*/
+ {
+ if (!PyArg_ParseTuple(args, "d:Matrix.rotation", &radians))
+ break;
+ cairo_matrix_init_identity(&result_matrix);
+ cairo_matrix_rotate(&result_matrix, radians);
+ result = PycairoMatrix_FromMatrix(&result_matrix);
+ }
+ while (0);
+ return result;
+ } /*matrix_rotation*/
+
+static PyObject *
+matrix_inverse(PycairoMatrix *self, PyObject *args_unused)
+ {
+ PyObject * result = NULL;
+ cairo_matrix_t result_matrix;
+ do /*once*/
+ {
+ result_matrix = self->matrix;
+ if (Pycairo_Check_Status(cairo_matrix_invert(&result_matrix)))
+ break;
+ result = PycairoMatrix_FromMatrix(&result_matrix);
+ }
+ while (0);
+ return result;
+ } /*matrix_inverse*/
+
+static PyObject *
matrix_item (PycairoMatrix *o, Py_ssize_t i) {
switch (i) {
case 0:
@@ -297,6 +367,11 @@ static PyMethodDef matrix_methods[] = {
{"transform_distance",(PyCFunction)matrix_transform_distance, METH_VARARGS },
{"transform_point", (PyCFunction)matrix_transform_point, METH_VARARGS },
{"translate", (PyCFunction)matrix_translate, METH_VARARGS },
+ /* functional methods: */
+ {"translation", (PyCFunction)matrix_translation, METH_VARARGS | METH_STATIC },
+ {"scaling", (PyCFunction)matrix_scaling, METH_VARARGS | METH_STATIC },
+ {"rotation", (PyCFunction)matrix_rotation, METH_VARARGS | METH_STATIC },
+ {"inverse", (PyCFunction)matrix_inverse, METH_VARARGS },
{NULL, NULL, 0, NULL},
};
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top