[cairo] [PATCH] add functional matrix-returning methods to Pycairo

Stuart Axon stuaxo2 at yahoo.com
Wed May 5 09:35:15 PDT 2010


This isn't my patch, but I found it while googling for cairo Matrix stuff.
It looks like a good idea, just sent to the wrong list AFAICT:

I've dropped him an email suggesting to send it here, but haven't
heard anything back yet.

http://www.gossamer-threads.com/lists/python/python/826029
---- And theres the message, in case you don't want to click on the
     above link to the message ----
from: ldo at geek-central.gen.nz <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}, 
}; 


      


More information about the cairo mailing list