[pygobject] Add cairo marshaling support for non-introspected signals
- From: Simon Feltman <sfeltman src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject] Add cairo marshaling support for non-introspected signals
- Date: Tue, 6 May 2014 03:52:10 +0000 (UTC)
commit de827d00762f2a741f90bc38f8b55518593f4509
Author: Simon Feltman <sfeltman src gnome org>
Date: Sun Mar 23 01:59:00 2014 -0700
Add cairo marshaling support for non-introspected signals
Add link dependency of cairo-gobject to _gi_cairo_la needed for retrieving
the GTypes of cairo classes.
Add GValue marshalers for cairo Context, Surface, FontFace, ScaledFont,
and Pattern classes.
https://bugzilla.gnome.org/show_bug.cgi?id=694604
gi/Makefile.am | 2 +
gi/pygi-foreign-cairo.c | 186 +++++++++++++++++++++++++++++++++++++++++++++++
gi/pygi-type.h | 1 +
gi/pygtype.c | 2 +
tests/test_cairo.py | 65 ++++++++++++++++
5 files changed, 256 insertions(+), 0 deletions(-)
---
diff --git a/gi/Makefile.am b/gi/Makefile.am
index 61e4ee7..6fb1c5d 100644
--- a/gi/Makefile.am
+++ b/gi/Makefile.am
@@ -140,12 +140,14 @@ _gi_cairo_la_SOURCES = \
pygi-foreign-cairo.c
_gi_cairo_la_CFLAGS = \
$(GI_CFLAGS) \
+ $(CAIRO_CFLAGS) \
$(PYCAIRO_CFLAGS)
_gi_cairo_la_CPPFLAGS = \
$(extension_cppflags)
_gi_cairo_la_LIBADD = \
$(extension_libadd) \
$(GI_LIBS) \
+ $(CAIRO_LIBS) \
$(PYCAIRO_LIBS)
_gi_cairo_la_LDFLAGS = \
$(extension_ldflags) \
diff --git a/gi/pygi-foreign-cairo.c b/gi/pygi-foreign-cairo.c
index a53ae4f..5937759 100644
--- a/gi/pygi-foreign-cairo.c
+++ b/gi/pygi-foreign-cairo.c
@@ -31,6 +31,8 @@ static Pycairo_CAPI_t *Pycairo_CAPI;
#include <pycairo/py3cairo.h>
#endif
+#include <cairo-gobject.h>
+
/* Limit includes from PyGI to APIs which do not have link dependencies
* (pygobject.h and pygi-foreign-api.h) since _gi_cairo is built as a separate
* shared library that interacts with PyGI through a PyCapsule API at runtime.
@@ -38,6 +40,10 @@ static Pycairo_CAPI_t *Pycairo_CAPI;
#include <pygi-foreign-api.h>
#include <pyglib-python-compat.h>
+/*
+ * cairo_t marshaling
+ */
+
static PyObject *
cairo_context_to_arg (PyObject *value,
GIInterfaceInfo *interface_info,
@@ -70,6 +76,7 @@ cairo_context_from_arg (GIInterfaceInfo *interface_info,
return PycairoContext_FromContext (context, &PycairoContext_Type, NULL);
}
+
static PyObject *
cairo_context_release (GIBaseInfo *base_info,
gpointer struct_)
@@ -78,6 +85,36 @@ cairo_context_release (GIBaseInfo *base_info,
Py_RETURN_NONE;
}
+static int
+cairo_context_to_gvalue (GValue *value, PyObject *obj)
+{
+ cairo_t *cr = PycairoContext_GET (obj);
+ if (!cr) {
+ return -1;
+ }
+
+ /* PycairoContext_GET returns a borrowed reference, use set_boxed
+ * to add new ref to the context which will be managed by the GValue. */
+ g_value_set_boxed (value, cr);
+ return 0;
+}
+
+static PyObject *
+cairo_context_from_gvalue (const GValue *value)
+{
+ /* PycairoContext_FromContext steals a ref, so we dup it out of the GValue. */
+ cairo_t *cr = g_value_dup_boxed (value);
+ if (!cr) {
+ return NULL;
+ }
+
+ return PycairoContext_FromContext (cr, &PycairoContext_Type, NULL);
+}
+
+
+/*
+ * cairo_surface_t marshaling
+ */
static PyObject *
cairo_surface_to_arg (PyObject *value,
@@ -120,6 +157,36 @@ cairo_surface_release (GIBaseInfo *base_info,
Py_RETURN_NONE;
}
+static int
+cairo_surface_to_gvalue (GValue *value, PyObject *obj)
+{
+ cairo_surface_t *surface = ((PycairoSurface*) obj)->surface;
+ if (!surface) {
+ return -1;
+ }
+
+ /* surface is a borrowed reference, use set_boxed
+ * to add new ref to the context which will be managed by the GValue. */
+ g_value_set_boxed (value, surface);
+ return 0;
+}
+
+static PyObject *
+cairo_surface_from_gvalue (const GValue *value)
+{
+ /* PycairoSurface_FromSurface steals a ref, so we dup it out of the GValue. */
+ cairo_surface_t *surface = g_value_dup_boxed (value);
+ if (!surface) {
+ return NULL;
+ }
+
+ return PycairoSurface_FromSurface (surface, NULL);
+}
+
+
+/*
+ * cairo_path_t marshaling
+ */
static PyObject *
cairo_path_to_arg (PyObject *value,
@@ -164,6 +231,39 @@ cairo_path_release (GIBaseInfo *base_info,
Py_RETURN_NONE;
}
+
+/*
+ * cairo_font_face_t marshaling
+ */
+
+static int
+cairo_font_face_to_gvalue (GValue *value, PyObject *obj)
+{
+ cairo_font_face_t *font_face = ((PycairoFontFace*) obj)->font_face;
+ if (!font_face) {
+ return -1;
+ }
+
+ g_value_set_boxed (value, font_face);
+ return 0;
+}
+
+static PyObject *
+cairo_font_face_from_gvalue (const GValue *value)
+{
+ cairo_font_face_t *font_face = g_value_dup_boxed (value);
+ if (!font_face) {
+ return NULL;
+ }
+
+ return PycairoFontFace_FromFontFace (font_face);
+}
+
+
+/*
+ * cairo_font_options_t marshaling
+ */
+
static PyObject *
cairo_font_options_to_arg (PyObject *value,
GIInterfaceInfo *interface_info,
@@ -205,6 +305,69 @@ cairo_font_options_release (GIBaseInfo *base_info,
Py_RETURN_NONE;
}
+
+/*
+ * scaled_font_t marshaling
+ */
+
+static int
+cairo_scaled_font_to_gvalue (GValue *value, PyObject *obj)
+{
+ cairo_scaled_font_t *scaled_font = ((PycairoScaledFont*) obj)->scaled_font;
+ if (!scaled_font) {
+ return -1;
+ }
+
+ /* scaled_font is a borrowed reference, use set_boxed
+ * to add new ref to the context which will be managed by the GValue. */
+ g_value_set_boxed (value, scaled_font);
+ return 0;
+}
+
+static PyObject *
+cairo_scaled_font_from_gvalue (const GValue *value)
+{
+ /* PycairoScaledFont_FromScaledFont steals a ref, so we dup it out of the GValue. */
+ cairo_scaled_font_t *scaled_font = g_value_dup_boxed (value);
+ if (!scaled_font) {
+ return NULL;
+ }
+
+ return PycairoScaledFont_FromScaledFont (scaled_font);
+}
+
+
+/*
+ * cairo_pattern_t marshaling
+ */
+
+static int
+cairo_pattern_to_gvalue (GValue *value, PyObject *obj)
+{
+ cairo_pattern_t *pattern = ((PycairoPattern*) obj)->pattern;
+ if (!pattern) {
+ return -1;
+ }
+
+ /* pattern is a borrowed reference, use set_boxed
+ * to add new ref to the context which will be managed by the GValue. */
+ g_value_set_boxed (value, pattern);
+ return 0;
+}
+
+static PyObject *
+cairo_pattern_from_gvalue (const GValue *value)
+{
+ /* PycairoPattern_FromPattern steals a ref, so we dup it out of the GValue. */
+ cairo_pattern_t *pattern = g_value_dup_boxed (value);
+ if (!pattern) {
+ return NULL;
+ }
+
+ return PycairoPattern_FromPattern (pattern, NULL);
+}
+
+
static PyMethodDef _gi_cairo_functions[] = { {0,} };
PYGLIB_MODULE_START(_gi_cairo, "_gi_cairo")
{
@@ -217,6 +380,8 @@ PYGLIB_MODULE_START(_gi_cairo, "_gi_cairo")
if (Pycairo_CAPI == NULL)
return PYGLIB_MODULE_ERROR_RETURN;
+ pygobject_init (3, 13, 2);
+
pygi_register_foreign_struct ("cairo",
"Context",
cairo_context_to_arg,
@@ -240,5 +405,26 @@ PYGLIB_MODULE_START(_gi_cairo, "_gi_cairo")
cairo_font_options_to_arg,
cairo_font_options_from_arg,
cairo_font_options_release);
+
+ pyg_register_gtype_custom (CAIRO_GOBJECT_TYPE_CONTEXT,
+ cairo_context_from_gvalue,
+ cairo_context_to_gvalue);
+
+ pyg_register_gtype_custom (CAIRO_GOBJECT_TYPE_SURFACE,
+ cairo_surface_from_gvalue,
+ cairo_surface_to_gvalue);
+
+ pyg_register_gtype_custom (CAIRO_GOBJECT_TYPE_FONT_FACE,
+ cairo_font_face_from_gvalue,
+ cairo_font_face_to_gvalue);
+
+ pyg_register_gtype_custom (CAIRO_GOBJECT_TYPE_SCALED_FONT,
+ cairo_scaled_font_from_gvalue,
+ cairo_scaled_font_to_gvalue);
+
+ pyg_register_gtype_custom (CAIRO_GOBJECT_TYPE_PATTERN,
+ cairo_pattern_from_gvalue,
+ cairo_pattern_to_gvalue);
+
}
PYGLIB_MODULE_END;
diff --git a/gi/pygi-type.h b/gi/pygi-type.h
index fdac5c0..85f7551 100644
--- a/gi/pygi-type.h
+++ b/gi/pygi-type.h
@@ -21,6 +21,7 @@
#define __PYGI_TYPE_H__
#include <Python.h>
+#include <girepository.h>
G_BEGIN_DECLS
diff --git a/gi/pygtype.c b/gi/pygtype.c
index 131a271..5957e5c 100644
--- a/gi/pygtype.c
+++ b/gi/pygtype.c
@@ -28,6 +28,7 @@
#include "pygparamspec.h"
#include "pygtype.h"
+#include "pygi-type.h"
#include "pygi-value.h"
/* -------------- __gtype__ objects ---------------------------- */
@@ -621,6 +622,7 @@ pyg_type_lookup(GType type)
/* recursively lookup types */
while (ptype) {
+ pygi_type_import_by_g_type (ptype);
if ((tm = g_type_get_qdata(ptype, pyg_type_marshal_key)) != NULL)
break;
ptype = g_type_parent(ptype);
diff --git a/tests/test_cairo.py b/tests/test_cairo.py
index e4ef65a..fdf86a2 100644
--- a/tests/test_cairo.py
+++ b/tests/test_cairo.py
@@ -7,6 +7,7 @@ import unittest
import gi
try:
+ gi.require_foreign('cairo')
import cairo
from gi.repository import Regress
has_cairo = True
@@ -19,6 +20,8 @@ try:
except:
Gtk = None
+from gi.repository import GObject
+
@unittest.skipUnless(has_cairo, 'built without cairo support')
class Test(unittest.TestCase):
@@ -72,5 +75,67 @@ class TestPango(unittest.TestCase):
self.assertEqual(type(font_opts.get_subpixel_order()), int)
+if has_cairo:
+ from gi.repository import cairo as CairoGObject
+
+ # Use PyGI signals to test non-introspected foreign marshaling.
+ class CairoSignalTester(GObject.Object):
+ sig_context = GObject.Signal(arg_types=[CairoGObject.Context])
+ sig_surface = GObject.Signal(arg_types=[CairoGObject.Surface])
+ sig_font_face = GObject.Signal(arg_types=[CairoGObject.FontFace])
+ sig_scaled_font = GObject.Signal(arg_types=[CairoGObject.ScaledFont])
+ sig_pattern = GObject.Signal(arg_types=[CairoGObject.Pattern])
+
+
+ unittest skipUnless(has_cairo, 'built without cairo support')
+class TestSignalMarshaling(unittest.TestCase):
+ # Tests round tripping of cairo objects through non-introspected signals.
+
+ def setUp(self):
+ self.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10)
+ self.context = cairo.Context(self.surface)
+ self.tester = CairoSignalTester()
+
+ def pass_object_through_signal(self, obj, signal):
+ """Pass the given `obj` through the `signal` emission storing the
+ `obj` passed through the signal and returning it."""
+ passthrough_result = []
+
+ def callback(instance, passthrough):
+ passthrough_result.append(passthrough)
+
+ signal.connect(callback)
+ signal.emit(obj)
+
+ return passthrough_result[0]
+
+ def test_context(self):
+ result = self.pass_object_through_signal(self.context, self.tester.sig_context)
+ self.assertTrue(isinstance(result, cairo.Context))
+
+ def test_surface(self):
+ result = self.pass_object_through_signal(self.surface, self.tester.sig_surface)
+ self.assertTrue(isinstance(result, cairo.Surface))
+
+ def test_font_face(self):
+ font_face = self.context.get_font_face()
+ result = self.pass_object_through_signal(font_face, self.tester.sig_font_face)
+ self.assertTrue(isinstance(result, cairo.FontFace))
+
+ def test_scaled_font(self):
+ scaled_font = cairo.ScaledFont(self.context.get_font_face(),
+ cairo.Matrix(),
+ cairo.Matrix(),
+ self.context.get_font_options())
+ result = self.pass_object_through_signal(scaled_font, self.tester.sig_scaled_font)
+ self.assertTrue(isinstance(result, cairo.ScaledFont))
+
+ def test_pattern(self):
+ pattern = cairo.SolidPattern(1, 1, 1, 1)
+ result = self.pass_object_through_signal(pattern, self.tester.sig_pattern)
+ self.assertTrue(isinstance(result, cairo.Pattern))
+ self.assertTrue(isinstance(result, cairo.SolidPattern))
+
+
if __name__ == '__main__':
unittest.main()
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]