/* -*- mode: C; c-basic-offset: 2 -*-
*
* Copyright © 2003,2010 James Henstridge, Steven Chaplin
*
* This file is part of pycairo.
*
* Pycairo is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License version 3 as published
* by the Free Software Foundation.
*
* Pycairo is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
* more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with pycairo. If not, see .
*/
#define PY_SSIZE_T_CLEAN
#include
#include "config.h"
#include "private.h"
/* PycairoMatrix_FromMatrix
* Create a new PycairoMatrix from a cairo_matrix_t
* matrix - a cairo_matrix_t to 'wrap' into a Python object.
* the cairo_matrix_t values are copied.
* Return value: New reference or NULL on failure
*/
PyObject *
PycairoMatrix_FromMatrix (const cairo_matrix_t *matrix) {
assert (matrix != NULL);
PyObject *o = PycairoMatrix_Type.tp_alloc (&PycairoMatrix_Type, 0);
if (o != NULL)
((PycairoMatrix *)o)->matrix = *matrix; // copy struct
return o;
}
static void
matrix_dealloc (PycairoMatrix *o) {
//o->ob_type->tp_free((PyObject *)o);
Py_TYPE(o)->tp_free(o);
}
static PyObject *
matrix_new (PyTypeObject *type, PyObject *args, PyObject *kwds) {
static char *kwlist[] = { "xx", "yx", "xy", "yy", "x0", "y0", NULL };
double xx = 1.0, yx = 0.0, xy = 0.0, yy = 1.0, x0 = 0.0, y0 = 0.0;
if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|dddddd:Matrix.__init__", kwlist,
&xx, &yx, &xy, &yy, &x0, &y0))
return NULL;
cairo_matrix_t mx;
cairo_matrix_init (&mx, xx, yx, xy, yy, x0, y0);
return PycairoMatrix_FromMatrix (&mx);
}
static PyObject *
matrix_init_rotate (PyTypeObject *type, PyObject *args) {
cairo_matrix_t matrix;
double radians;
if (!PyArg_ParseTuple(args, "d:Matrix.init_rotate", &radians))
return NULL;
cairo_matrix_init_rotate (&matrix, radians);
return PycairoMatrix_FromMatrix (&matrix);
}
static PyObject *
matrix_invert (PycairoMatrix *o) {
if (Pycairo_Check_Status (cairo_matrix_invert (&o->matrix)))
return NULL;
Py_RETURN_NONE;
}
/* cairo_matrix_multiply */
static PyObject *
matrix_multiply (PycairoMatrix *o, PyObject *args) {
PycairoMatrix *mx2;
if (!PyArg_ParseTuple(args, "O!:Matrix.multiply",
&PycairoMatrix_Type, &mx2))
return NULL;
cairo_matrix_t result;
cairo_matrix_multiply (&result, &o->matrix, &mx2->matrix);
return PycairoMatrix_FromMatrix (&result);
}
/* standard matrix multiply, for use by '*' operator */
static PyObject *
matrix_operator_multiply (PycairoMatrix *o, PycairoMatrix *o2) {
cairo_matrix_t result;
cairo_matrix_multiply (&result, &o->matrix, &o2->matrix);
return PycairoMatrix_FromMatrix (&result);
}
static PyObject *
matrix_repr (PycairoMatrix *o) {
char buf[256];
PyOS_snprintf(buf, sizeof(buf), "cairo.Matrix(%g, %g, %g, %g, %g, %g)",
o->matrix.xx, o->matrix.yx,
o->matrix.xy, o->matrix.yy,
o->matrix.x0, o->matrix.y0);
return PyUnicode_FromString(buf);
}
static PyObject *
matrix_richcmp (PycairoMatrix *m1, PycairoMatrix *m2, int op) {
int equal;
PyObject *ret;
cairo_matrix_t *mx1 = &m1->matrix;
cairo_matrix_t *mx2 = &m2->matrix;
if (!PyObject_TypeCheck(m2, &PycairoMatrix_Type) ||
!(op == Py_EQ || op == Py_NE)) {
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
equal = mx1->xx == mx2->xx && mx1->yx == mx2->yx &&
mx1->xy == mx2->xy && mx1->yy == mx2->yy &&
mx1->x0 == mx2->x0 && mx1->y0 == mx2->y0;
if (op == Py_EQ)
ret = equal ? Py_True : Py_False;
else
ret = equal ? Py_False : Py_True;
Py_INCREF(ret);
return ret;
}
static PyObject *
matrix_rotate (PycairoMatrix *o, PyObject *args) {
double radians;
if (!PyArg_ParseTuple(args, "d:Matrix.rotate", &radians))
return NULL;
cairo_matrix_rotate (&o->matrix, radians);
Py_RETURN_NONE;
}
static PyObject *
matrix_scale (PycairoMatrix *o, PyObject *args) {
double sx, sy;
if (!PyArg_ParseTuple(args, "dd:Matrix.scale", &sx, &sy))
return NULL;
cairo_matrix_scale (&o->matrix, sx, sy);
Py_RETURN_NONE;
}
static PyObject *
matrix_transform_distance (PycairoMatrix *o, PyObject *args) {
double dx, dy;
if (!PyArg_ParseTuple(args, "dd:Matrix.transform_distance", &dx, &dy))
return NULL;
cairo_matrix_transform_distance (&o->matrix, &dx, &dy);
return Py_BuildValue("(dd)", dx, dy);
}
static PyObject *
matrix_transform_point (PycairoMatrix *o, PyObject *args) {
double x, y;
if (!PyArg_ParseTuple(args, "dd:Matrix.transform_point", &x, &y))
return NULL;
cairo_matrix_transform_point (&o->matrix, &x, &y);
return Py_BuildValue("(dd)", x, y);
}
static PyObject *
matrix_translate (PycairoMatrix *o, PyObject *args) {
double tx, ty;
if (!PyArg_ParseTuple(args, "dd:Matrix.translate", &tx, &ty))
return NULL;
cairo_matrix_translate (&o->matrix, tx, ty);
Py_RETURN_NONE;
}
static PyObject *
matrix_item (PycairoMatrix *o, Py_ssize_t i) {
switch (i) {
case 0:
return Py_BuildValue("d", o->matrix.xx);
case 1:
return Py_BuildValue("d", o->matrix.yx);
case 2:
return Py_BuildValue("d", o->matrix.xy);
case 3:
return Py_BuildValue("d", o->matrix.yy);
case 4:
return Py_BuildValue("d", o->matrix.x0);
case 5:
return Py_BuildValue("d", o->matrix.y0);
default:
PyErr_SetString(PyExc_IndexError, "Matrix index out of range");
return NULL;
}
}
static PyNumberMethods matrix_as_number = {
0, /* nb_add*/
0, /* nb_subtract*/
(binaryfunc)matrix_operator_multiply, /* nb_multiply*/
0, /* nb_remainder*/
0, /* nb_divmod*/
0, /* nb_power*/
0, /* nb_negative*/
0, /* nb_positive*/
0, /* nb_absolute*/
0, /* nb_bool*/
0, /* nb_invert*/
0, /* nb_lshift*/
0, /* nb_rshift*/
0, /* nb_and*/
0, /* nb_xor*/
0, /* nb_or*/
0, /* nb_int*/
0, /* nb_reserved*/
0, /* nb_float*/
0, /* nb_inplace_add*/
0, /* nb_inplace_subtract*/
0, /* nb_inplace_multiply*/
0, /* nb_inplace_divide*/
0, /* nb_inplace_remainder*/
0, /* nb_inplace_power*/
0, /* nb_inplace_lshift*/
0, /* nb_inplace_rshift*/
0, /* nb_inplace_and*/
0, /* nb_inplace_xor*/
0, /* nb_inplace_or*/
0, /* nb_floor_divide */
0, /* nb_true_divide */
0, /* nb_inplace_floor_divide */
0, /* nb_inplace_true_divide */
// 0, /* nb_index */
};
static PySequenceMethods matrix_as_sequence = {
0, /* sq_length */
0, /* sq_concat */
0, /* sq_repeat */
(ssizeargfunc)matrix_item, /* sq_item */
0, /* sq_slice */
0, /* sq_ass_item */
0, /* sq_ass_slice */
0, /* sq_contains */
};
static PyMethodDef matrix_methods[] = {
/* Do not need to wrap all cairo_matrix_init_*() functions
* C API Matrix constructors Python equivalents
* cairo_matrix_init() cairo.Matrix(xx,yx,xy,yy,x0,y0)
* cairo_matrix_init_rotate() cairo.Matrix.init_rotate(radians)
* cairo_matrix_init_identity() cairo.Matrix()
* cairo_matrix_init_translate() cairo.Matrix(x0=x0,y0=y0)
* cairo_matrix_init_scale() cairo.Matrix(xx=xx,yy=yy)
*/
{"init_rotate", (PyCFunction)matrix_init_rotate, METH_VARARGS | METH_CLASS },
{"invert", (PyCFunction)matrix_invert, METH_NOARGS },
{"multiply", (PyCFunction)matrix_multiply, METH_VARARGS },
{"rotate", (PyCFunction)matrix_rotate, METH_VARARGS },
{"scale", (PyCFunction)matrix_scale, METH_VARARGS },
{"transform_distance",(PyCFunction)matrix_transform_distance, METH_VARARGS },
{"transform_point", (PyCFunction)matrix_transform_point, METH_VARARGS },
{"translate", (PyCFunction)matrix_translate, METH_VARARGS },
{NULL, NULL, 0, NULL},
};
PyTypeObject PycairoMatrix_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
//PyObject_HEAD_INIT(NULL)
//0, /* ob_size */
"cairo.Matrix", /* tp_name */
sizeof(PycairoMatrix), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)matrix_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
(reprfunc)matrix_repr, /* tp_repr */
&matrix_as_number, /* tp_as_number */
&matrix_as_sequence, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
NULL, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
(richcmpfunc)matrix_richcmp, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
matrix_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
(newfunc)matrix_new, /* tp_new */
0, /* tp_free */
0, /* tp_is_gc */
0, /* tp_bases */
};