[dia] pydia: Renderer:draw_object() and Object::draw() via Python



commit 3cf5a400d9924a7dc6fc5e67cec166a466885887
Author: Hans Breuer <hans breuer org>
Date:   Fri Jan 7 22:09:01 2011 +0100

    pydia: Renderer:draw_object() and Object::draw() via Python
    
    Allows to interweave additional object information with the rendering.
    See diasvg.py for an example. Basic idea from dia-list:
    http://mail.gnome.org/archives/dia-list/2010-November/msg00019.html

 plug-ins/python/diasvg.py      |    4 +++
 plug-ins/python/pydia-object.c |   32 ++++++++++++++++++++++++++-
 plug-ins/python/pydia-render.c |   47 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 82 insertions(+), 1 deletions(-)
---
diff --git a/plug-ins/python/diasvg.py b/plug-ins/python/diasvg.py
index 9aac0db..cd79de8 100644
--- a/plug-ins/python/diasvg.py
+++ b/plug-ins/python/diasvg.py
@@ -46,6 +46,10 @@ class SvgRenderer :
 	def end_render (self) :
 		self.f.write('</svg>')
 		self.f.close()
+	def draw_object (self, object, matrix) :
+		self.f.write("<!-- " + object.type.name + " -->\n")
+		# don't forget to render the object
+		object.draw (self)
 	def set_linewidth (self, width) :
 		if width < 0.001 : # zero line width is invisble ?
 			self.line_width = 0.001
diff --git a/plug-ins/python/pydia-object.c b/plug-ins/python/pydia-object.c
index 28adc7c..d9d289e 100644
--- a/plug-ins/python/pydia-object.c
+++ b/plug-ins/python/pydia-object.c
@@ -24,6 +24,7 @@
 #include "pydia-handle.h"
 #include "pydia-geometry.h"
 #include "pydia-properties.h"
+#include "pydia-render.h"
 
 #include <structmember.h> /* PyMemberDef */
 
@@ -87,7 +88,33 @@ PyDiaObject_Destroy(PyDiaObject *self, PyObject *args)
     return Py_None;
 }
 
-/* draw */
+static PyObject *
+PyDiaObject_Draw(PyDiaObject *self, PyObject *args)
+{
+    PyObject* renderer;
+    DiaRenderer *wrapper;
+
+    if (!PyArg_ParseTuple(args, "O:Object.draw", &renderer))
+	return NULL;
+
+    /* We need to create the PythonRenderer wrapper to provide the gobject interface.
+     * This could be done much more efficient if it would somehow be cached for the
+     * whole rendering pass ...
+     */
+    wrapper = PyDia_new_renderer_wrapper (renderer);
+
+    if (!self->object->ops->draw) {
+	PyErr_SetString(PyExc_RuntimeError,"object does not implement method");
+	return NULL;
+    }
+
+    self->object->ops->draw(self->object, wrapper);
+
+    g_object_unref (wrapper);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
 
 static PyObject *
 PyDiaObject_DistanceFrom(PyDiaObject *self, PyObject *args)
@@ -189,6 +216,9 @@ static PyMethodDef PyDiaObject_Methods[] = {
       "  Calculate the object's distance from the given point." },
     { "copy", (PyCFunction)PyDiaObject_Copy, METH_VARARGS,
       "copy() -> Object.  Create a new object copy." },
+    { "draw", (PyCFunction)PyDiaObject_Draw, METH_VARARGS,
+      "draw(dia.Renderer: r) -> None."
+      "  Draw the object with the given renderer" },
     { "move", (PyCFunction)PyDiaObject_Move, METH_VARARGS,
       "move(real: x, real: y) -> None."
       "  Move the entire object. The given point is the new object.obj_pos." },
diff --git a/plug-ins/python/pydia-render.c b/plug-ins/python/pydia-render.c
index d43a8e0..74707a5 100644
--- a/plug-ins/python/pydia-render.c
+++ b/plug-ins/python/pydia-render.c
@@ -37,6 +37,7 @@
 #include "pydia-font.h"
 #include "pydia-image.h"
 #include "pydia-error.h"
+#include "pydia-render.h"
 
 /*
  * The PyDiaRenderer is currently defined in Python only. The
@@ -328,6 +329,39 @@ set_font(DiaRenderer *renderer, DiaFont *font, real height)
 static gpointer parent_class = NULL;
 
 static void
+draw_object (DiaRenderer *renderer, DiaObject *object, DiaMatrix *matrix)
+{
+  PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer);
+
+  func = PyObject_GetAttrString (self, "draw_object");
+  if (func && PyCallable_Check(func)) {
+    PyObject *mat = NULL;
+
+    Py_INCREF(self);
+    Py_INCREF(func);
+    if (matrix)
+      mat = PyDiaMatrix_New (matrix);
+    else {
+      Py_INCREF(Py_None);
+      mat = Py_None;
+    }
+    arg = Py_BuildValue ("(OO)", PyDiaObject_New (object), mat );
+    if (arg) {
+      res = PyEval_CallObject (func, arg);
+      ON_RES(res, FALSE);
+    }
+    Py_XDECREF (arg);
+    Py_XDECREF (mat);
+    Py_DECREF(func);
+    Py_DECREF(self);
+  } else { /* member optional */
+    PyErr_Clear();
+    /* but should still call the base class */
+    DIA_RENDERER_CLASS (parent_class)->draw_object (renderer, object, matrix);
+  }
+}
+
+static void
 draw_line(DiaRenderer *renderer, 
           Point *start, Point *end, 
           Color *line_colour)
@@ -798,6 +832,17 @@ PyDia_export_data(DiagramData *data, const gchar *filename,
   g_object_unref(renderer);
 }
 
+DiaRenderer *
+PyDia_new_renderer_wrapper (PyObject *self)
+{
+  DiaPyRenderer *wrapper;
+  
+  wrapper = g_object_new (DIA_TYPE_PY_RENDERER, NULL);
+  wrapper->self = self;
+  
+  return DIA_RENDERER (wrapper);
+}
+
 /*
  * GObject boiler plate
  */
@@ -857,6 +902,8 @@ dia_py_renderer_class_init (DiaPyRendererClass *klass)
   renderer_class->begin_render = begin_render;
   renderer_class->end_render   = end_render;
 
+  renderer_class->draw_object  = draw_object;
+
   renderer_class->set_linewidth  = set_linewidth;
   renderer_class->set_linecaps   = set_linecaps;
   renderer_class->set_linejoin   = set_linejoin;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]