diff options
Diffstat (limited to 'src/pycairo-matrix.c')
-rw-r--r-- | src/pycairo-matrix.c | 365 |
1 files changed, 365 insertions, 0 deletions
diff --git a/src/pycairo-matrix.c b/src/pycairo-matrix.c new file mode 100644 index 0000000..73f1845 --- /dev/null +++ b/src/pycairo-matrix.c @@ -0,0 +1,365 @@ +/* -*- mode: C; c-basic-offset: 4 -*- + * + * Pycairo - Python bindings for cairo + * + * Copyright © 2003 James Henstridge, Steven Chaplin + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + */ + +#define PY_SSIZE_T_CLEAN +#include <Python.h> + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include "pycairo-private.h" + + +/* PycairoMatrix_FromMatrix + * Create a new PycairoMatrix from a cairo_matrix_t + * matrix - a cairo_matrix_t to 'wrap' into a Python object + * Return value: New reference or NULL on failure + */ +PyObject * +PycairoMatrix_FromMatrix (const cairo_matrix_t *matrix) +{ + PyObject *o; + assert (matrix != NULL); + o = PycairoMatrix_Type.tp_alloc (&PycairoMatrix_Type, 0); + if (o != NULL) + ((PycairoMatrix *)o)->matrix = *matrix; + return o; +} + +static void +matrix_dealloc (PycairoMatrix *o) +{ + o->ob_type->tp_free((PyObject *)o); +} + +static PyObject * +matrix_new (PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyObject *o; + 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; + + o = type->tp_alloc(type, 0); + if (o) + cairo_matrix_init (&((PycairoMatrix *)o)->matrix, + xx, yx, xy, yy, x0, y0); + return o; +} + +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 PyString_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 = { + (binaryfunc)0, /*nb_add*/ + (binaryfunc)0, /*nb_subtract*/ + (binaryfunc)matrix_operator_multiply, /*nb_multiply*/ + (binaryfunc)0, /*nb_divide*/ + (binaryfunc)0, /*nb_remainder*/ + (binaryfunc)0, /*nb_divmod*/ + (ternaryfunc)0, /*nb_power*/ + (unaryfunc)0, /*nb_negative*/ + (unaryfunc)0, /*nb_positive*/ + (unaryfunc)0, /*nb_absolute*/ + (inquiry)0, /*nb_nonzero*/ + (unaryfunc)0, /*nb_invert*/ + (binaryfunc)0, /*nb_lshift*/ + (binaryfunc)0, /*nb_rshift*/ + (binaryfunc)0, /*nb_and*/ + (binaryfunc)0, /*nb_xor*/ + (binaryfunc)0, /*nb_or*/ + (coercion)0, /*nb_coerce*/ + (unaryfunc)0, /*nb_int*/ + (unaryfunc)0, /*nb_long*/ + (unaryfunc)0, /*nb_float*/ + (unaryfunc)0, /*nb_oct*/ + (unaryfunc)0, /*nb_hex*/ + 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*/ + (binaryfunc)0, /* nb_floor_divide */ + 0, /* nb_true_divide */ + 0, /* nb_inplace_floor_divide */ + 0, /* nb_inplace_true_divide */ + (unaryfunc)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 = { + 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, /* &PyBaseObject_Type, */ /* 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 */ +}; |