diff options
Diffstat (limited to 'src/pattern.c')
-rw-r--r-- | src/pattern.c | 585 |
1 files changed, 585 insertions, 0 deletions
diff --git a/src/pattern.c b/src/pattern.c new file mode 100644 index 0000000..0676114 --- /dev/null +++ b/src/pattern.c @@ -0,0 +1,585 @@ +/* -*- mode: C; c-basic-offset: 2 -*- + * + * Copyright © 2004-2006,2010 Steve 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 <http://www.gnu.org/licenses/>. + */ + +#define PY_SSIZE_T_CLEAN +#include <Python.h> + +#include "config.h" +#include "private.h" + + +/* Class Pattern ---------------------------------------------------------- */ + +/* PycairoPattern_FromPattern + * Create a new + * PycairoSolidPattern, + * PycairoSurfacePattern, + * PycairoLinearGradient, or + * PycairoRadialGradient from a cairo_pattern_t. + * pattern - a cairo_pattern_t to 'wrap' into a Python object. + * It is unreferenced if the PycairoPattern creation fails, or if the + * pattern has an error status. + * base - the base object used to create the pattern, or NULL. + * It is referenced to keep it alive while the cairo_pattern_t is being used. + * For PycairoSurfacePattern base should be the PycairoSurface, for other + # patterns it should be NULL. + * Return value: New reference or NULL on failure + */ +PyObject * +PycairoPattern_FromPattern (cairo_pattern_t *pattern, PyObject *base) { + PyTypeObject *type = NULL; + PyObject *o; + + assert (pattern != NULL); + + if (Pycairo_Check_Status (cairo_pattern_status (pattern))) { + cairo_pattern_destroy (pattern); + return NULL; + } + + switch (cairo_pattern_get_type (pattern)) { + case CAIRO_PATTERN_TYPE_SOLID: + type = &PycairoSolidPattern_Type; + break; + case CAIRO_PATTERN_TYPE_SURFACE: + type = &PycairoSurfacePattern_Type; + break; + case CAIRO_PATTERN_TYPE_LINEAR: + type = &PycairoLinearGradient_Type; + break; + case CAIRO_PATTERN_TYPE_RADIAL: + type = &PycairoRadialGradient_Type; + break; + default: + type = &PycairoPattern_Type; + break; + } + + o = type->tp_alloc(type, 0); + if (o == NULL) { + cairo_pattern_destroy (pattern); + } else { + ((PycairoPattern *)o)->pattern = pattern; + Py_XINCREF(base); + ((PycairoPattern *)o)->base = base; + } + return o; +} + +static void +pattern_dealloc (PycairoPattern *o) { + if (o->pattern) { + cairo_pattern_destroy (o->pattern); + o->pattern = NULL; + } + Py_CLEAR(o->base); + + o->ob_type->tp_free((PyObject *)o); +} + +static PyObject * +pattern_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { + PyErr_SetString(PyExc_TypeError, + "The Pattern type cannot be instantiated"); + return NULL; +} + +static PyObject * +pattern_get_extend (PycairoPattern *o) { + return PyInt_FromLong (cairo_pattern_get_extend (o->pattern)); +} + +static PyObject * +pattern_get_matrix (PycairoPattern *o) { + cairo_matrix_t matrix; + cairo_pattern_get_matrix (o->pattern, &matrix); + return PycairoMatrix_FromMatrix (&matrix); +} + +static PyObject * +pattern_set_extend (PycairoPattern *o, PyObject *args) { + int extend; + + if (!PyArg_ParseTuple(args, "i:Pattern.set_extend", &extend)) + return NULL; + + cairo_pattern_set_extend (o->pattern, extend); + Py_RETURN_NONE; +} + +static PyObject * +pattern_set_matrix (PycairoPattern *o, PyObject *args) { + PycairoMatrix *m; + + if (!PyArg_ParseTuple (args, "O!:Pattern.set_matrix", + &PycairoMatrix_Type, &m)) + return NULL; + + cairo_pattern_set_matrix (o->pattern, &m->matrix); + Py_RETURN_NONE; +} + +static PyMethodDef pattern_methods[] = { + /* methods never exposed in a language binding: + * cairo_pattern_destroy() + * cairo_pattern_get_type() + * cairo_pattern_reference() + * + * cairo_pattern_status() + * - not needed since Pycairo handles status checking + */ + {"get_extend", (PyCFunction)pattern_get_extend, METH_NOARGS }, + {"get_matrix", (PyCFunction)pattern_get_matrix, METH_NOARGS }, + {"set_extend", (PyCFunction)pattern_set_extend, METH_VARARGS }, + {"set_matrix", (PyCFunction)pattern_set_matrix, METH_VARARGS }, + {NULL, NULL, 0, NULL}, +}; + +PyTypeObject PycairoPattern_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "cairo.Pattern", /* tp_name */ + sizeof(PycairoPattern), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)pattern_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* 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 | Py_TPFLAGS_BASETYPE,/* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + pattern_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)pattern_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ +}; + + +/* Class SolidPattern ----------------------------------------------------- */ + +static PyObject * +solid_pattern_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { + double r, g, b, a = 1.0; + if (!PyArg_ParseTuple (args, "ddd|d:SolidPattern.__new__", &r, &g, &b, &a)) + return NULL; + return PycairoPattern_FromPattern (cairo_pattern_create_rgba (r, g, b, a), + NULL); +} + +static PyObject * +solid_pattern_get_rgba (PycairoSolidPattern *o) { + double red, green, blue, alpha; + cairo_pattern_get_rgba (o->pattern, &red, &green, &blue, &alpha); + return Py_BuildValue("(dddd)", red, green, blue, alpha); +} + +static PyMethodDef solid_pattern_methods[] = { + {"get_rgba", (PyCFunction)solid_pattern_get_rgba, METH_NOARGS }, + {NULL, NULL, 0, NULL}, +}; + +PyTypeObject PycairoSolidPattern_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "cairo.SolidPattern", /* tp_name */ + sizeof(PycairoSolidPattern), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* 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 */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + solid_pattern_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &PycairoPattern_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + (newfunc)solid_pattern_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ +}; + +/* Class SurfacePattern --------------------------------------------------- */ + +static PyObject * +surface_pattern_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { + PycairoSurface *s; + if (!PyArg_ParseTuple (args, "O!:SurfacePattern.__new__", + &PycairoSurface_Type, &s)) + return NULL; + return PycairoPattern_FromPattern ( + cairo_pattern_create_for_surface (s->surface), (PyObject *)s); +} + +static PyObject * +surface_pattern_get_filter (PycairoSurfacePattern *o) { + return PyInt_FromLong (cairo_pattern_get_filter (o->pattern)); +} + +static PyObject * +surface_pattern_get_surface (PycairoSurfacePattern *o) { + /* + cairo_surface_t *surface; + cairo_pattern_get_surface (o->pattern, &surface); + return PycairoSurface_FromSurface ( + cairo_surface_reference (surface), NULL); + */ + /* return the surface used to create the pattern */ + return Py_BuildValue("O", o->base); +} + +static PyObject * +surface_pattern_set_filter (PycairoSurfacePattern *o, PyObject *args) { + int filter; + + if (!PyArg_ParseTuple (args, "i:SurfacePattern.set_filter", &filter)) + return NULL; + + cairo_pattern_set_filter (o->pattern, filter); + Py_RETURN_NONE; +} + +static PyMethodDef surface_pattern_methods[] = { + {"get_filter", (PyCFunction)surface_pattern_get_filter, METH_NOARGS }, + {"get_surface", (PyCFunction)surface_pattern_get_surface, METH_NOARGS }, + {"set_filter", (PyCFunction)surface_pattern_set_filter, METH_VARARGS }, + {NULL, NULL, 0, NULL}, +}; + +PyTypeObject PycairoSurfacePattern_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "cairo.SurfacePattern", /* tp_name */ + sizeof(PycairoSurfacePattern), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* 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 */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + surface_pattern_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &PycairoPattern_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + (newfunc)surface_pattern_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ +}; + +/* Class Gradient --------------------------------------------------------- */ + +static PyObject * +gradient_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { + PyErr_SetString(PyExc_TypeError, + "The Gradient type cannot be instantiated"); + return NULL; +} + +static PyObject * +gradient_add_color_stop_rgb (PycairoGradient *o, PyObject *args) { + double offset, red, green, blue; + if (!PyArg_ParseTuple(args, "dddd:Gradient.add_color_stop_rgb", + &offset, &red, &green, &blue)) + return NULL; + cairo_pattern_add_color_stop_rgb (o->pattern, offset, red, green, blue); + RETURN_NULL_IF_CAIRO_PATTERN_ERROR(o->pattern); + Py_RETURN_NONE; +} + +static PyObject * +gradient_add_color_stop_rgba (PycairoGradient *o, PyObject *args) { + double offset, red, green, blue, alpha; + if (!PyArg_ParseTuple(args, "ddddd:Gradient.add_color_stop_rgba", + &offset, &red, &green, &blue, &alpha)) + return NULL; + cairo_pattern_add_color_stop_rgba (o->pattern, offset, red, + green, blue, alpha); + RETURN_NULL_IF_CAIRO_PATTERN_ERROR(o->pattern); + Py_RETURN_NONE; +} + +static PyMethodDef gradient_methods[] = { + {"add_color_stop_rgb",(PyCFunction)gradient_add_color_stop_rgb, + METH_VARARGS }, + {"add_color_stop_rgba",(PyCFunction)gradient_add_color_stop_rgba, + METH_VARARGS }, + {NULL, NULL, 0, NULL}, +}; + +PyTypeObject PycairoGradient_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "cairo.Gradient", /* tp_name */ + sizeof(PycairoGradient), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* 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 | Py_TPFLAGS_BASETYPE,/* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + gradient_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &PycairoPattern_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + (newfunc)gradient_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ +}; + +/* Class LinearGradient --------------------------------------------------- */ + +static PyObject * +linear_gradient_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { + double x0, y0, x1, y1; + if (!PyArg_ParseTuple(args, "dddd:LinearGradient.__new__", + &x0, &y0, &x1, &y1)) + return NULL; + return PycairoPattern_FromPattern ( + cairo_pattern_create_linear (x0, y0, x1, y1), NULL); +} + +static PyObject * +linear_gradient_get_linear_points (PycairoLinearGradient *o) { + double x0, y0, x1, y1; + cairo_pattern_get_linear_points (o->pattern, &x0, &y0, &x1, &y1); + return Py_BuildValue("(dddd)", x0, y0, x1, y1); +} + +static PyMethodDef linear_gradient_methods[] = { + {"get_linear_points", (PyCFunction)linear_gradient_get_linear_points, + METH_NOARGS }, + {NULL, NULL, 0, NULL}, +}; + +PyTypeObject PycairoLinearGradient_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "cairo.LinearGradient", /* tp_name */ + sizeof(PycairoLinearGradient), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* 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 */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + linear_gradient_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &PycairoGradient_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + (newfunc)linear_gradient_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ +}; + +/* Class RadialGradient --------------------------------------------------- */ + +static PyObject * +radial_gradient_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { + double cx0, cy0, radius0, cx1, cy1, radius1; + if (!PyArg_ParseTuple(args, "dddddd:RadialGradient.__new__", + &cx0, &cy0, &radius0, &cx1, &cy1, &radius1)) + return NULL; + return PycairoPattern_FromPattern ( + cairo_pattern_create_radial (cx0, cy0, radius0, cx1, cy1, radius1), + NULL); +} + +static PyObject * +radial_gradient_get_radial_circles (PycairoRadialGradient *o) { + double x0, y0, r0, x1, y1, r1; + cairo_pattern_get_radial_circles (o->pattern, &x0, &y0, &r0, + &x1, &y1, &r1); + return Py_BuildValue("(dddddd)", x0, y0, r0, x1, y1, r1); +} + +static PyMethodDef radial_gradient_methods[] = { + {"get_radial_circles", (PyCFunction)radial_gradient_get_radial_circles, + METH_NOARGS }, + {NULL, NULL, 0, NULL}, +}; + +PyTypeObject PycairoRadialGradient_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "cairo.RadialGradient", /* tp_name */ + sizeof(PycairoRadialGradient), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* 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 */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + radial_gradient_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &PycairoGradient_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + (newfunc)radial_gradient_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ +}; |