OSDN Git Service

fix brushlib Python exception handling
authorMartin Renold <martinxyz@gmx.ch>
Sun, 24 Jul 2011 09:36:05 +0000 (11:36 +0200)
committerBen O'Steen <bosteen@gmail.com>
Mon, 1 Aug 2011 12:48:30 +0000 (13:48 +0100)
Return NULL from the original python call (stroke_to) if an
exception has occurred while trying to get the tile memory.

Also, move some Python specific code away from brushlib.

brushlib/brush.hpp
lib/brush.py
lib/mypaintlib.hpp
lib/mypaintlib.i
lib/python_brush.hpp [new file with mode: 0644]
lib/tiledsurface.hpp

index 2056fb5..d10c397 100644 (file)
@@ -104,22 +104,34 @@ public:
   }
 
   void set_base_value (int id, float value) {
-    g_assert (id >= 0 && id < BRUSH_SETTINGS_COUNT);
+    assert (id >= 0 && id < BRUSH_SETTINGS_COUNT);
     settings[id]->base_value = value;
 
     settings_base_values_have_changed ();
   }
 
   void set_mapping_n (int id, int input, int n) {
-    g_assert (id >= 0 && id < BRUSH_SETTINGS_COUNT);
+    assert (id >= 0 && id < BRUSH_SETTINGS_COUNT);
     settings[id]->set_n (input, n);
   }
 
   void set_mapping_point (int id, int input, int index, float x, float y) {
-    g_assert (id >= 0 && id < BRUSH_SETTINGS_COUNT);
+    assert (id >= 0 && id < BRUSH_SETTINGS_COUNT);
     settings[id]->set_point (input, index, x, y);
   }
 
+  float get_state (int i)
+  {
+    assert (i >= 0 && i < STATE_COUNT);
+    return states[i];
+  }
+
+  void set_state (int i, float value)
+  {
+    assert (i >= 0 && i < STATE_COUNT);
+    states[i] = value;
+  }
+
 private:
   // returns the fraction still left after t seconds
   float exp_decay (float T_const, float t)
@@ -767,26 +779,4 @@ public:
     return false;
   }
 
-  PyObject * get_state ()
-  {
-    npy_intp dims = {STATE_COUNT};
-    PyObject * data = PyArray_SimpleNew(1, &dims, NPY_FLOAT32);
-    npy_float32 * data_p = (npy_float32*)PyArray_DATA(data);
-    for (int i=0; i<STATE_COUNT; i++) {
-      data_p[i] = states[i];
-    }
-    return data;
-  }
-
-  void set_state (PyObject * data)
-  {
-    assert(PyArray_NDIM(data) == 1);
-    assert(PyArray_DIM(data, 0) == STATE_COUNT);
-    assert(PyArray_ISCARRAY(data));
-    npy_float32 * data_p = (npy_float32*)PyArray_DATA(data);
-    for (int i=0; i<STATE_COUNT; i++) {
-      states[i] = data_p[i];
-    }
-  }
-
 };
index a817728..7d89d23 100644 (file)
@@ -358,17 +358,23 @@ class BrushInfo:
         return r
 
 
-class Brush(mypaintlib.Brush):
+class Brush(mypaintlib.PythonBrush):
     """
     Low-level extension of the C brush class, propagating all changes of
     a brushinfo instance down into the C code.
     """
     def __init__(self, brushinfo):
-        mypaintlib.Brush.__init__(self)
+        mypaintlib.PythonBrush.__init__(self)
         self.brushinfo = brushinfo
         brushinfo.observers.append(self.update_brushinfo)
         self.update_brushinfo(all_settings)
 
+        # override some mypaintlib.Brush methods with special wrappers
+        # from python_brush.hpp
+        self.get_state = self.python_get_state
+        self.set_state = self.python_set_state
+        self.stroke_to = self.python_stroke_to
+
     def update_brushinfo(self, settings):
         """Mirror changed settings into the BrushInfo tracking this Brush."""
 
index 3c867f2..68f88c5 100644 (file)
@@ -1,6 +1,7 @@
 #include "Python.h"
 #include "numpy/arrayobject.h"
 #include "../brushlib/brushlib.hpp"
+#include "python_brush.hpp"
 #include "brushmodes.hpp"
 #include "tiledsurface.hpp"
 #include "pixops.hpp"
index e499ded..3aa2b4b 100644 (file)
@@ -8,6 +8,7 @@ typedef struct { int x, y, w, h; } Rect;
 %include "../brushlib/surface.hpp"
 %include "../brushlib/brush.hpp"
 %include "../brushlib/mapping.hpp"
+%include "python_brush.hpp"
 %include "brushmodes.hpp"
 %include "tiledsurface.hpp"
 %include "pixops.hpp"
diff --git a/lib/python_brush.hpp b/lib/python_brush.hpp
new file mode 100644 (file)
index 0000000..4ca53ab
--- /dev/null
@@ -0,0 +1,58 @@
+/* brushlib - The MyPaint Brush Library
+ * Copyright (C) 2011 Martin Renold <martinxyz@gmx.ch>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+class PythonBrush : public Brush {
+
+public:
+  // get state as numpy array
+  PyObject * python_get_state ()
+  {
+    npy_intp dims = {STATE_COUNT};
+    PyObject * data = PyArray_SimpleNew(1, &dims, NPY_FLOAT32);
+    npy_float32 * data_p = (npy_float32*)PyArray_DATA(data);
+    for (int i=0; i<STATE_COUNT; i++) {
+      data_p[i] = get_state(i);
+    }
+    return data;
+  }
+
+  // set state from numpy array
+  void python_set_state (PyObject * data)
+  {
+    assert(PyArray_NDIM(data) == 1);
+    assert(PyArray_DIM(data, 0) == STATE_COUNT);
+    assert(PyArray_ISCARRAY(data));
+    npy_float32 * data_p = (npy_float32*)PyArray_DATA(data);
+    for (int i=0; i<STATE_COUNT; i++) {
+      set_state(i, data_p[i]);
+    }
+  }
+
+  // same as stroke_to() but with exception handling, should an
+  // exception happen in the surface code (eg. out-of-memory)
+  PyObject* python_stroke_to (Surface * surface, float x, float y, float pressure, float xtilt, float ytilt, double dtime)
+  {
+    bool res = stroke_to (surface, x, y, pressure, xtilt, ytilt, dtime);
+    if (PyErr_Occurred()) {
+      return NULL;
+    } else if (res) {
+      Py_RETURN_TRUE;
+    } else {
+      Py_RETURN_FALSE;
+    }
+  }
+
+};
index 2a70925..384e5b9 100644 (file)
@@ -68,9 +68,10 @@ public:
         return tileMemory[i].rgba_p;
       }
     }
+    if (PyErr_Occurred()) return NULL;
     PyObject* rgba = PyObject_CallMethod(self, "get_tile_memory", "(iii)", tx, ty, readonly);
     if (rgba == NULL) {
-      printf("Python exception during get_tile_memory()! The next traceback might be wrong.\n");
+      printf("Python exception during get_tile_memory()!\n");
       return NULL;
     }
 #ifdef HEAVY_DEBUG