summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@gmail.com>2011-05-20 16:34:52 -0600
committerTavian Barnes <tavianator@gmail.com>2011-05-20 16:34:52 -0600
commit250b980002419746fc099c7633b9600a15afb1c6 (patch)
treec146041da19654d565a6dc433eebada324fc9fb9
parentad716acc7fa7fd151ff96fe6d17f0ba1a3a66379 (diff)
downloaddimension-250b980002419746fc099c7633b9600a15afb1c6.tar.xz
Add Canvases to the Python module.
-rw-r--r--libdimension-python/Canvas.c171
-rw-r--r--libdimension-python/Canvas.h30
-rw-r--r--libdimension-python/Makefile.am4
-rw-r--r--libdimension-python/Scene.c22
-rw-r--r--libdimension-python/dimension.c4
-rw-r--r--libdimension-python/tests/Makefile.am1
-rwxr-xr-xlibdimension-python/tests/canvas.py57
-rwxr-xr-xlibdimension-python/tests/demo.py13
8 files changed, 290 insertions, 12 deletions
diff --git a/libdimension-python/Canvas.c b/libdimension-python/Canvas.c
new file mode 100644
index 0000000..6cce310
--- /dev/null
+++ b/libdimension-python/Canvas.c
@@ -0,0 +1,171 @@
+/*************************************************************************
+ * Copyright (C) 2009-2011 Tavian Barnes <tavianator@tavianator.com> *
+ * *
+ * This file is part of The Dimension Python Module. *
+ * *
+ * The Dimension Python Module is free software; you can redistribute it *
+ * and/ or modify it under the terms of the GNU Lesser General Public *
+ * License as published by the Free Software Foundation; either version *
+ * 3 of the License, or (at your option) any later version. *
+ * *
+ * The Dimension Python Module 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 this program. If not, see *
+ * <http://www.gnu.org/licenses/>. *
+ *************************************************************************/
+
+#include "Color.h"
+#include "Canvas.h"
+
+static int
+dmnsn_py_Canvas_init(dmnsn_py_Canvas *self, PyObject *args, PyObject *kwds)
+{
+ static char *kwlist[] = { "width", "height", NULL };
+
+ Py_ssize_t width, height;
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "nn", kwlist, &width, &height))
+ return -1;
+
+ if (width < 0 || height < 0) {
+ PyErr_SetString(PyExc_ValueError, "Canvas dimensions must be positive");
+ return -1;
+ }
+
+ dmnsn_delete_canvas(self->canvas);
+ self->canvas = dmnsn_new_canvas(width, height);
+ DMNSN_INCREF(self->canvas);
+ dmnsn_clear_canvas(self->canvas, dmnsn_black);
+ return 0;
+}
+
+static void
+dmnsn_py_Canvas_dealloc(dmnsn_py_Canvas *self)
+{
+ dmnsn_delete_canvas(self->canvas);
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static PyObject *
+dmnsn_py_Canvas_optimizePNG(dmnsn_py_Canvas *self)
+{
+ if (dmnsn_png_optimize_canvas(self->canvas) != 0)
+ return PyErr_SetFromErrno(PyExc_OSError);
+
+ /* Re-clear the canvas to clear the optimizer too */
+ dmnsn_clear_canvas(self->canvas, dmnsn_black);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+dmnsn_py_Canvas_optimizeGL(dmnsn_py_Canvas *self)
+{
+ if (dmnsn_gl_optimize_canvas(self->canvas) != 0)
+ return PyErr_SetFromErrno(PyExc_OSError);
+
+ /* Re-clear the canvas to clear the optimizer too */
+ dmnsn_clear_canvas(self->canvas, dmnsn_black);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+dmnsn_py_Canvas_clear(dmnsn_py_Canvas *self, PyObject *args, PyObject *kwds)
+{
+ dmnsn_color color;
+ if (!dmnsn_py_Color_args(&color, args, kwds))
+ return NULL;
+
+ dmnsn_clear_canvas(self->canvas, color);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+dmnsn_py_Canvas_writePNG(dmnsn_py_Canvas *self, PyObject *args)
+{
+ PyObject *filenameobj;
+ if (!PyArg_ParseTuple(args, "O&", PyUnicode_FSConverter, &filenameobj))
+ return NULL;
+
+ const char *filename = PyBytes_AS_STRING(filenameobj);
+ FILE *file = fopen(filename, "wb");
+ if (!file)
+ return PyErr_SetFromErrno(PyExc_OSError);
+
+ if (dmnsn_png_write_canvas(self->canvas, file) != 0)
+ return PyErr_SetFromErrno(PyExc_OSError);
+
+ if (fclose(file) != 0)
+ return PyErr_SetFromErrno(PyExc_OSError);
+
+ Py_DECREF(filenameobj);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+dmnsn_py_Canvas_drawGL(dmnsn_py_Canvas *self)
+{
+ if (dmnsn_gl_write_canvas(self->canvas) != 0)
+ return PyErr_SetFromErrno(PyExc_OSError);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyMethodDef dmnsn_py_Canvas_methods[] = {
+ { "optimizePNG", (PyCFunction)dmnsn_py_Canvas_optimizePNG, METH_NOARGS,
+ "Optimize a canvas for PNG output" },
+ { "optimizeGL", (PyCFunction)dmnsn_py_Canvas_optimizeGL, METH_NOARGS,
+ "Optimize a canvas for OpenGL output" },
+ { "clear", (PyCFunction)dmnsn_py_Canvas_clear, METH_VARARGS | METH_KEYWORDS,
+ "Clear a canvas with a solid color" },
+ { "writePNG", (PyCFunction)dmnsn_py_Canvas_writePNG, METH_VARARGS,
+ "Write a canvas to a PNG file" },
+ { "drawGL", (PyCFunction)dmnsn_py_Canvas_drawGL, METH_NOARGS,
+ "Draw a canvas to the screen with OpenGL" },
+ { NULL }
+};
+
+static PyObject *
+dmnsn_py_Canvas_get_width(dmnsn_py_Canvas *self, void *closure)
+{
+ return PyLong_FromSize_t(self->canvas->width);
+}
+
+static PyObject *
+dmnsn_py_Canvas_get_height(dmnsn_py_Canvas *self, void *closure)
+{
+ return PyLong_FromSize_t(self->canvas->height);
+}
+
+static PyGetSetDef dmnsn_py_Canvas_getsetters[] = {
+ { "width", (getter)dmnsn_py_Canvas_get_width, NULL, "Canvas width", NULL },
+ { "height", (getter)dmnsn_py_Canvas_get_height, NULL, "Canvas height", NULL },
+ { NULL }
+};
+
+PyTypeObject dmnsn_py_CanvasType = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ .tp_name = "dimension.Canvas",
+ .tp_basicsize = sizeof(dmnsn_py_Canvas),
+ .tp_dealloc = (destructor)dmnsn_py_Canvas_dealloc,
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+ .tp_doc = "Dimension canvas",
+ .tp_methods = dmnsn_py_Canvas_methods,
+ .tp_getset = dmnsn_py_Canvas_getsetters,
+ .tp_init = (initproc)dmnsn_py_Canvas_init,
+};
+
+bool
+dmnsn_py_init_CanvasType(void)
+{
+ dmnsn_py_CanvasType.tp_new = PyType_GenericNew;
+ return PyType_Ready(&dmnsn_py_CanvasType) >= 0;
+}
diff --git a/libdimension-python/Canvas.h b/libdimension-python/Canvas.h
new file mode 100644
index 0000000..53d09c1
--- /dev/null
+++ b/libdimension-python/Canvas.h
@@ -0,0 +1,30 @@
+/*************************************************************************
+ * Copyright (C) 2009-2011 Tavian Barnes <tavianator@tavianator.com> *
+ * *
+ * This file is part of The Dimension Python Module. *
+ * *
+ * The Dimension Python Module is free software; you can redistribute it *
+ * and/ or modify it under the terms of the GNU Lesser General Public *
+ * License as published by the Free Software Foundation; either version *
+ * 3 of the License, or (at your option) any later version. *
+ * *
+ * The Dimension Python Module 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 this program. If not, see *
+ * <http://www.gnu.org/licenses/>. *
+ *************************************************************************/
+
+#include "dimension-python.h"
+
+typedef struct dmnsn_py_Canvas {
+ PyObject_HEAD
+ dmnsn_canvas *canvas;
+} dmnsn_py_Canvas;
+
+extern PyTypeObject dmnsn_py_CanvasType;
+
+bool dmnsn_py_init_CanvasType(void);
diff --git a/libdimension-python/Makefile.am b/libdimension-python/Makefile.am
index e75ffad..e2d2049 100644
--- a/libdimension-python/Makefile.am
+++ b/libdimension-python/Makefile.am
@@ -26,7 +26,9 @@ AM_CFLAGS = $(Python_CFLAGS)
AM_LDFLAGS = $(Python_LDFLAGS)
pyexec_LTLIBRARIES = dimension.la
-dimension_la_SOURCES = Color.c \
+dimension_la_SOURCES = Canvas.c \
+ Canvas.h \
+ Color.c \
Color.h \
Matrix.c \
Matrix.h \
diff --git a/libdimension-python/Scene.c b/libdimension-python/Scene.c
index 6323402..29a623a 100644
--- a/libdimension-python/Scene.c
+++ b/libdimension-python/Scene.c
@@ -18,20 +18,22 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+#include "Canvas.h"
#include "Scene.h"
-static PyObject *
-dmnsn_py_Scene_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- dmnsn_py_Scene *self;
- self = (dmnsn_py_Scene *)type->tp_alloc(type, 0);
- self->scene = dmnsn_new_scene();
- return (PyObject *)self;
-}
-
static int
dmnsn_py_Scene_init(dmnsn_py_Scene *self, PyObject *args, PyObject *kwds)
{
+ static char *kwlist[] = { "canvas", NULL };
+
+ dmnsn_py_Canvas *canvas;
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist,
+ &dmnsn_py_CanvasType, &canvas))
+ return -1;
+
+ dmnsn_delete_scene(self->scene);
+ self->scene = dmnsn_new_scene();
+ dmnsn_scene_set_canvas(self->scene, canvas->canvas);
return 0;
}
@@ -60,11 +62,11 @@ PyTypeObject dmnsn_py_SceneType = {
.tp_methods = dmnsn_py_Scene_methods,
.tp_getset = dmnsn_py_Scene_getsetters,
.tp_init = (initproc)dmnsn_py_Scene_init,
- .tp_new = dmnsn_py_Scene_new,
};
bool
dmnsn_py_init_SceneType(void)
{
+ dmnsn_py_SceneType.tp_new = PyType_GenericNew;
return PyType_Ready(&dmnsn_py_SceneType) >= 0;
}
diff --git a/libdimension-python/dimension.c b/libdimension-python/dimension.c
index f47dfbc..03e2aaa 100644
--- a/libdimension-python/dimension.c
+++ b/libdimension-python/dimension.c
@@ -22,6 +22,7 @@
#include "Vector.h"
#include "Matrix.h"
#include "Color.h"
+#include "Canvas.h"
#include "Scene.h"
static PyObject *
@@ -73,6 +74,7 @@ PyInit_dimension(void)
if (!dmnsn_py_init_VectorType()
|| !dmnsn_py_init_MatrixType()
|| !dmnsn_py_init_ColorType()
+ || !dmnsn_py_init_CanvasType()
|| !dmnsn_py_init_SceneType())
return NULL;
@@ -104,6 +106,8 @@ PyInit_dimension(void)
PyModule_AddObject(module, "Yellow", (PyObject *)&dmnsn_py_Yellow);
PyModule_AddObject(module, "Cyan", (PyObject *)&dmnsn_py_Cyan);
+ PyModule_AddObject(module, "Canvas", (PyObject *)&dmnsn_py_CanvasType);
+
PyModule_AddObject(module, "Scene", (PyObject *)&dmnsn_py_SceneType);
return module;
diff --git a/libdimension-python/tests/Makefile.am b/libdimension-python/tests/Makefile.am
index 48e1129..70c2f35 100644
--- a/libdimension-python/tests/Makefile.am
+++ b/libdimension-python/tests/Makefile.am
@@ -19,6 +19,7 @@
TESTS = geometry.py \
color.py \
+ canvas.py \
demo.py
TESTS_ENVIRONMENT = PYTHONPATH=$(top_builddir)/libdimension-python/.libs
diff --git a/libdimension-python/tests/canvas.py b/libdimension-python/tests/canvas.py
new file mode 100755
index 0000000..e69d2d9
--- /dev/null
+++ b/libdimension-python/tests/canvas.py
@@ -0,0 +1,57 @@
+#!/usr/bin/python3
+
+#########################################################################
+# Copyright (C) 2010-2011 Tavian Barnes <tavianator@tavianator.com> #
+# #
+# This file is part of The Dimension Test Suite. #
+# #
+# The Dimension Test Suite is free software; you can redistribute it #
+# and/or modify it under the terms of the GNU General Public License as #
+# published by the Free Software Foundation; either version 3 of the #
+# License, or (at your option) any later version. #
+# #
+# The Dimension Test Suite 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 #
+# General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+#########################################################################
+
+from dimension import *
+import errno
+
+# Treat warnings as errors for tests
+dieOnWarnings(True)
+
+canvas = Canvas(768, 480)
+
+assert canvas.width == 768, canvas.width
+assert canvas.height == 480, canvas.height
+
+havePNG = True
+try:
+ canvas.optimizePNG()
+except OSError as e:
+ if e.errno == errno.ENOSYS:
+ havePNG = False
+ else:
+ raise
+
+haveGL = True
+try:
+ canvas.optimizeGL()
+except OSError as e:
+ if e.errno == errno.ENOSYS:
+ haveGL = False
+ else:
+ raise
+
+canvas.clear(Blue)
+
+if havePNG:
+ canvas.writePNG('png.png')
+
+#if haveGL:
+# canvas.drawGL()
diff --git a/libdimension-python/tests/demo.py b/libdimension-python/tests/demo.py
index e9cdc7b..187f4ef 100755
--- a/libdimension-python/tests/demo.py
+++ b/libdimension-python/tests/demo.py
@@ -24,4 +24,15 @@ from dimension import *
# Treat warnings as errors for tests
dieOnWarnings(True)
-scene = Scene()
+canvas = Canvas(width = 768, height = 480)
+
+havePNG = True
+try:
+ canvas.optimizePNG()
+except OSError as e:
+ if e.errno == errno.ENOSYS:
+ havePNG = False
+ else:
+ raise
+
+scene = Scene(canvas = canvas)