summaryrefslogtreecommitdiff
path: root/src/pycairo-path.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pycairo-path.c')
-rw-r--r--src/pycairo-path.c337
1 files changed, 337 insertions, 0 deletions
diff --git a/src/pycairo-path.c b/src/pycairo-path.c
new file mode 100644
index 0000000..7473f14
--- /dev/null
+++ b/src/pycairo-path.c
@@ -0,0 +1,337 @@
+/* -*- mode: C; c-basic-offset: 4 -*-
+ *
+ * Pycairo - Python bindings for cairo
+ *
+ * Copyright © 2005 Steve 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"
+
+
+/* PycairoPath iterator object
+ * modelled on Python-2.4/Objects/rangeobject.c and tupleobject.c
+ */
+
+/* PycairoPath_FromPath
+ * Create a new PycairoPath from a cairo_path_t
+ * path - a cairo_path_t to 'wrap' into a Python object.
+ * path is unreferenced if the PycairoPath creation fails, or if path
+ * is in an error status.
+ * Return value: New reference or NULL on failure
+ */
+PyObject *
+PycairoPath_FromPath (cairo_path_t *path)
+{
+ PyObject *o;
+
+ assert (path != NULL);
+
+ if (Pycairo_Check_Status (path->status)) {
+ cairo_path_destroy (path);
+ return NULL;
+ }
+
+ o = PycairoPath_Type.tp_alloc (&PycairoPath_Type, 0);
+ if (o)
+ ((PycairoPath *)o)->path = path;
+ else
+ cairo_path_destroy (path);
+ return o;
+}
+
+static void
+path_dealloc(PycairoPath *p)
+{
+#ifdef DEBUG
+ printf("path_dealloc start\n");
+#endif
+ if (p->path) {
+ cairo_path_destroy(p->path);
+ p->path = NULL;
+ }
+ p->ob_type->tp_free((PyObject *)p);
+#ifdef DEBUG
+ printf("path_dealloc end\n");
+#endif
+}
+
+static PyObject *
+path_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ return type->tp_alloc(type, 0);
+ /* initializes memory to zeros */
+}
+
+static int
+path_init(PycairoPath *p, PyObject *args, PyObject *kwds)
+{
+ PyErr_SetString(PyExc_TypeError, "The Path type cannot be instantiated, "
+ "use Context.copy_path()");
+ return -1;
+}
+
+static PyObject *
+path_str(PycairoPath *p)
+{
+ PyObject *s, *pieces = NULL, *result = NULL;
+ cairo_path_t *path = p->path;
+ cairo_path_data_t *data;
+ int i, ret;
+ char buf[80];
+
+ pieces = PyList_New(0);
+ if (pieces == NULL)
+ goto Done;
+
+ /* loop reading elements */
+ for (i=0; i < path->num_data; i += path->data[i].header.length) {
+ data = &path->data[i];
+ switch (data->header.type) {
+
+ case CAIRO_PATH_MOVE_TO:
+ PyOS_snprintf(buf, sizeof(buf), "move_to %f %f",
+ data[1].point.x, data[1].point.y);
+ s = PyString_FromString(buf);
+ if (!s)
+ goto Done;
+ ret = PyList_Append(pieces, s);
+ Py_DECREF(s);
+ if (ret < 0)
+ goto Done;
+ break;
+
+ case CAIRO_PATH_LINE_TO:
+ PyOS_snprintf(buf, sizeof(buf), "line_to %f %f",
+ data[1].point.x, data[1].point.y);
+ s = PyString_FromString(buf);
+ if (!s)
+ goto Done;
+ ret = PyList_Append(pieces, s);
+ Py_DECREF(s);
+ if (ret < 0)
+ goto Done;
+ break;
+
+ case CAIRO_PATH_CURVE_TO:
+ PyOS_snprintf(buf, sizeof(buf), "curve_to %f %f %f %f %f %f",
+ data[1].point.x, data[1].point.y,
+ data[2].point.x, data[2].point.y,
+ data[3].point.x, data[3].point.y);
+ s = PyString_FromString(buf);
+ if (!s)
+ goto Done;
+ ret = PyList_Append(pieces, s);
+ Py_DECREF(s);
+ if (ret < 0)
+ goto Done;
+ break;
+
+ case CAIRO_PATH_CLOSE_PATH:
+ s = PyString_FromString("close path");
+ if (!s)
+ goto Done;
+ ret = PyList_Append(pieces, s);
+ Py_DECREF(s);
+ if (ret < 0)
+ goto Done;
+ break;
+ }
+ }
+ /* result = "\n".join(pieces) */
+ s = PyString_FromString("\n");
+ if (s == NULL)
+ goto Done;
+ result = _PyString_Join(s, pieces);
+ Py_DECREF(s);
+
+Done:
+ Py_XDECREF(pieces);
+ return result;
+}
+
+static PyObject * path_iter(PyObject *seq); /* forward declaration */
+
+
+PyTypeObject PycairoPath_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /* ob_size */
+ "cairo.Path", /* tp_name */
+ sizeof(PycairoPath), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)path_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 */
+ (reprfunc)path_str, /* 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 */
+ (getiterfunc)path_iter, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* 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 */
+ (initproc)path_init, /* tp_init */
+ 0, /* tp_alloc */
+ (newfunc)path_new, /* tp_new */
+};
+
+/*********************** PycairoPath Iterator **************************/
+
+typedef struct {
+ PyObject_HEAD
+ int index; /* position within PycairoPath */
+ PycairoPath *pypath; /* Set to NULL when iterator is exhausted */
+} PycairoPathiter;
+
+PyTypeObject PycairoPathiter_Type;
+
+
+static void
+pathiter_dealloc(PycairoPathiter *it)
+{
+ Py_XDECREF(it->pypath);
+ PyObject_Del(it);
+}
+
+static PyObject *
+path_iter(PyObject *pypath)
+{
+ PycairoPathiter *it;
+
+ if (!PyObject_TypeCheck (pypath, &PycairoPath_Type)) {
+ PyErr_BadInternalCall();
+ return NULL;
+ }
+ it = PyObject_New(PycairoPathiter, &PycairoPathiter_Type);
+ if (it == NULL)
+ return NULL;
+
+ it->index = 0;
+ Py_INCREF(pypath);
+ it->pypath = (PycairoPath *)pypath;
+ return (PyObject *) it;
+}
+
+static PyObject *
+pathiter_next(PycairoPathiter *it)
+{
+ PycairoPath *pypath;
+ cairo_path_t *path;
+
+ assert(it != NULL);
+ pypath = it->pypath;
+ if (pypath == NULL)
+ return NULL;
+ assert (PyObject_TypeCheck (pypath, &PycairoPath_Type));
+ path = pypath->path;
+
+ /* return the next path element, advance index */
+ if (it->index < path->num_data) {
+ cairo_path_data_t *data = &path->data[it->index];
+ int type = data->header.type;
+
+ it->index += data[0].header.length;
+
+ switch (type) {
+ case CAIRO_PATH_MOVE_TO:
+ case CAIRO_PATH_LINE_TO:
+ return Py_BuildValue("(i(dd))", type,
+ data[1].point.x, data[1].point.y);
+ case CAIRO_PATH_CURVE_TO:
+ return Py_BuildValue("(i(dddddd))", type,
+ data[1].point.x, data[1].point.y,
+ data[2].point.x, data[2].point.y,
+ data[3].point.x, data[3].point.y);
+ case CAIRO_PATH_CLOSE_PATH:
+ return Py_BuildValue("i()", type);
+ default:
+ PyErr_SetString(PyExc_RuntimeError, "unknown CAIRO_PATH type");
+ return NULL;
+ }
+ }
+
+ /* iterator has no remaining items */
+ Py_DECREF(pypath);
+ it->pypath = NULL;
+ return NULL;
+}
+
+PyTypeObject PycairoPathiter_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /* ob_size */
+ "cairo.Pathiter", /* tp_name */
+ sizeof(PycairoPathiter), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)pathiter_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, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* PyObject_SelfIter, */ /* tp_iter */
+ (iternextfunc)pathiter_next, /* tp_iternext */
+ 0, /* tp_methods */
+};