From 31a5a0c183264d2cb37fa4bee2acaec6d771340f Mon Sep 17 00:00:00 2001 From: Sean Vig Date: Thu, 21 May 2015 15:29:30 -0500 Subject: [PATCH] Update to use cffi 1.0 compilation mechanism Create two ffi's for the module in ffi_build, one for the cairo library, importing the ffi from xcffib (if it can be imported) and adding the relevant cdefs, and another ffi for the gdk_pixbuf cdefs. Now, to run cairocffi from source will require running `python cairocffi/ffi_build.py` to compile the ffi objects, these are handled automatically when installing. --- .gitignore | 1 + .travis.yml | 1 + MANIFEST.in | 1 + cairocffi/__init__.py | 4 +- cairocffi/ffi_build.py | 103 +++++++++++++++++++++++++++++++++++++++++ cairocffi/pixbuf.py | 69 +-------------------------- cairocffi/xcb.py | 12 ++--- setup.py | 9 +++- 8 files changed, 120 insertions(+), 80 deletions(-) create mode 100644 cairocffi/ffi_build.py diff --git a/.gitignore b/.gitignore index 223071c..bab1e4d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ *.pyc __pycache__ +cairocffi/_ffi*.py *.egg-info /dist /.tox diff --git a/.travis.yml b/.travis.yml index 0a1809e..436577b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,4 +9,5 @@ python: install: - "pip install xcffib" - "pip install ." + - "python cairocffi/ffi_build.py" script: "py.test" diff --git a/MANIFEST.in b/MANIFEST.in index 2675103..929665f 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,3 +1,4 @@ include README.rst CHANGES LICENSE tox.ini .coveragerc recursive-include docs * prune docs/_build +exclude cairocffi/_ffi*.py diff --git a/cairocffi/__init__.py b/cairocffi/__init__.py index 2b8f82b..ed5db97 100644 --- a/cairocffi/__init__.py +++ b/cairocffi/__init__.py @@ -11,11 +11,11 @@ """ import sys -from cffi import FFI from . import constants from .compat import FileNotFoundError +from ._ffi import ffi VERSION = '0.6' # pycairo compat: @@ -34,8 +34,6 @@ def dlopen(ffi, *names): return ffi.dlopen(names[0]) # pragma: no cover -ffi = FFI() -ffi.cdef(constants._CAIRO_HEADERS) CAIRO_NAMES = ['libcairo.so.2', 'libcairo.2.dylib', 'libcairo-2.dll', 'cairo', 'libcairo-2'] cairo = dlopen(ffi, *CAIRO_NAMES) diff --git a/cairocffi/ffi_build.py b/cairocffi/ffi_build.py new file mode 100644 index 0000000..c4d02a0 --- /dev/null +++ b/cairocffi/ffi_build.py @@ -0,0 +1,103 @@ +# coding: utf8 +""" + cairocffi.ffi_build + ~~~~~~~~~~~~~~~~~~~ + + Build the cffi bindings + + :copyright: Copyright 2013 by Simon Sapin + :license: BSD, see LICENSE for details. + +""" + +import os +import sys +from cffi import FFI + +# Path hack to import constants when this file is exec'd by setuptools +this_file = os.path.abspath(__file__) +this_dir = os.path.split(this_file)[0] +sys.path.append(this_dir) + +import constants + + +# Primary cffi definitions +ffi = FFI() +ffi.set_source('cairocffi._ffi', None) +ffi.cdef(constants._CAIRO_HEADERS) + +# include xcffib cffi definitions for cairo xcb support +try: + from xcffib.ffi_build import ffi as xcb_ffi + ffi.include(xcb_ffi) + ffi.cdef(constants._CAIRO_XCB_HEADERS) +except ImportError: + pass + +# gdk pixbuf cffi definitions +ffi_pixbuf = FFI() +ffi_pixbuf.set_source('cairocffi._ffi_pixbuf', None) +ffi_pixbuf.include(ffi) +ffi_pixbuf.cdef(''' + typedef unsigned long gsize; + typedef unsigned int guint32; + typedef unsigned int guint; + typedef unsigned char guchar; + typedef char gchar; + typedef int gint; + typedef gint gboolean; + typedef guint32 GQuark; + typedef void* gpointer; + typedef ... GdkPixbufLoader; + typedef ... GdkPixbufFormat; + typedef ... GdkPixbuf; + typedef struct { + GQuark domain; + gint code; + gchar *message; + } GError; + typedef enum { + GDK_COLORSPACE_RGB + } GdkColorspace; + + + GdkPixbufLoader * gdk_pixbuf_loader_new (void); + GdkPixbufFormat * gdk_pixbuf_loader_get_format (GdkPixbufLoader *loader); + GdkPixbuf * gdk_pixbuf_loader_get_pixbuf (GdkPixbufLoader *loader); + gboolean gdk_pixbuf_loader_write ( + GdkPixbufLoader *loader, const guchar *buf, gsize count, + GError **error); + gboolean gdk_pixbuf_loader_close ( + GdkPixbufLoader *loader, GError **error); + + gchar * gdk_pixbuf_format_get_name (GdkPixbufFormat *format); + + GdkColorspace gdk_pixbuf_get_colorspace (const GdkPixbuf *pixbuf); + int gdk_pixbuf_get_n_channels (const GdkPixbuf *pixbuf); + gboolean gdk_pixbuf_get_has_alpha (const GdkPixbuf *pixbuf); + int gdk_pixbuf_get_bits_per_sample (const GdkPixbuf *pixbuf); + int gdk_pixbuf_get_width (const GdkPixbuf *pixbuf); + int gdk_pixbuf_get_height (const GdkPixbuf *pixbuf); + int gdk_pixbuf_get_rowstride (const GdkPixbuf *pixbuf); + guchar * gdk_pixbuf_get_pixels (const GdkPixbuf *pixbuf); + gsize gdk_pixbuf_get_byte_length (const GdkPixbuf *pixbuf); + gboolean gdk_pixbuf_save_to_buffer ( + GdkPixbuf *pixbuf, gchar **buffer, gsize *buffer_size, + const char *type, GError **error, ...); + + void gdk_cairo_set_source_pixbuf ( + cairo_t *cr, const GdkPixbuf *pixbuf, + double pixbuf_x, double pixbuf_y); + + + void g_object_ref (gpointer object); + void g_object_unref (gpointer object); + void g_error_free (GError *error); + void g_type_init (void); +''') + + +if __name__ == '__main__': + ffi.compile() + ffi_pixbuf.compile() diff --git a/cairocffi/pixbuf.py b/cairocffi/pixbuf.py index de913aa..03fff9a 100644 --- a/cairocffi/pixbuf.py +++ b/cairocffi/pixbuf.py @@ -11,82 +11,17 @@ """ import sys -import ctypes from io import BytesIO from functools import partial from array import array -import cffi - -from . import ffi as cairo_ffi, dlopen, ImageSurface, Context, constants +from . import dlopen, ImageSurface, Context, constants +from ._ffi_pixbuf import ffi from .compat import xrange __all__ = ['decode_to_image_surface'] - -ffi = cffi.FFI() -ffi.include(cairo_ffi) -ffi.cdef(''' - - typedef unsigned long gsize; - typedef unsigned int guint32; - typedef unsigned int guint; - typedef unsigned char guchar; - typedef char gchar; - typedef int gint; - typedef gint gboolean; - typedef guint32 GQuark; - typedef void* gpointer; - typedef ... GdkPixbufLoader; - typedef ... GdkPixbufFormat; - typedef ... GdkPixbuf; - typedef struct { - GQuark domain; - gint code; - gchar *message; - } GError; - typedef enum { - GDK_COLORSPACE_RGB - } GdkColorspace; - - - GdkPixbufLoader * gdk_pixbuf_loader_new (void); - GdkPixbufFormat * gdk_pixbuf_loader_get_format (GdkPixbufLoader *loader); - GdkPixbuf * gdk_pixbuf_loader_get_pixbuf (GdkPixbufLoader *loader); - gboolean gdk_pixbuf_loader_write ( - GdkPixbufLoader *loader, const guchar *buf, gsize count, - GError **error); - gboolean gdk_pixbuf_loader_close ( - GdkPixbufLoader *loader, GError **error); - - gchar * gdk_pixbuf_format_get_name (GdkPixbufFormat *format); - - GdkColorspace gdk_pixbuf_get_colorspace (const GdkPixbuf *pixbuf); - int gdk_pixbuf_get_n_channels (const GdkPixbuf *pixbuf); - gboolean gdk_pixbuf_get_has_alpha (const GdkPixbuf *pixbuf); - int gdk_pixbuf_get_bits_per_sample (const GdkPixbuf *pixbuf); - int gdk_pixbuf_get_width (const GdkPixbuf *pixbuf); - int gdk_pixbuf_get_height (const GdkPixbuf *pixbuf); - int gdk_pixbuf_get_rowstride (const GdkPixbuf *pixbuf); - guchar * gdk_pixbuf_get_pixels (const GdkPixbuf *pixbuf); - gsize gdk_pixbuf_get_byte_length (const GdkPixbuf *pixbuf); - gboolean gdk_pixbuf_save_to_buffer ( - GdkPixbuf *pixbuf, gchar **buffer, gsize *buffer_size, - const char *type, GError **error, ...); - - void gdk_cairo_set_source_pixbuf ( - cairo_t *cr, const GdkPixbuf *pixbuf, - double pixbuf_x, double pixbuf_y); - - - void g_object_ref (gpointer object); - void g_object_unref (gpointer object); - void g_error_free (GError *error); - void g_type_init (void); - -''') - gdk_pixbuf = dlopen(ffi, 'gdk_pixbuf-2.0', 'libgdk_pixbuf-2.0-0', 'libgdk_pixbuf-2.0.so') gobject = dlopen(ffi, 'gobject-2.0', 'libgobject-2.0-0', 'libgobject-2.0.so') diff --git a/cairocffi/xcb.py b/cairocffi/xcb.py index 6a1bd33..606ca58 100644 --- a/cairocffi/xcb.py +++ b/cairocffi/xcb.py @@ -8,15 +8,11 @@ :copyright: Copyright 2014 by Simon Sapin :license: BSD, see LICENSE for details. """ -from xcffib import ffi as xcb_ffi, visualtype_to_c_struct +from xcffib import visualtype_to_c_struct -from . import ffi, dlopen, constants, CAIRO_NAMES +from . import cairo, constants from .surfaces import Surface, SURFACE_TYPE_TO_CLASS -ffi.include(xcb_ffi) -ffi.cdef(constants._CAIRO_XCB_HEADERS) -cairo_xcb = dlopen(ffi, *CAIRO_NAMES) - class XCBSurface(Surface): """The XCB surface is used to render cairo graphics to X Window System @@ -38,7 +34,7 @@ class XCBSurface(Surface): def __init__(self, conn, drawable, visual, width, height): c_visual = visualtype_to_c_struct(visual) - p = cairo_xcb.cairo_xcb_surface_create( + p = cairo.cairo_xcb_surface_create( conn._conn, drawable, c_visual, width, height) Surface.__init__(self, p) @@ -57,7 +53,7 @@ def set_size(self, width, height): :param width: integer :param height: integer """ - cairo_xcb.cairo_xcb_surface_set_size(self._pointer, width, height) + cairo.cairo_xcb_surface_set_size(self._pointer, width, height) self._check_status() SURFACE_TYPE_TO_CLASS[constants.SURFACE_TYPE_XCB] = XCBSurface diff --git a/setup.py b/setup.py index d373d4a..f98f072 100644 --- a/setup.py +++ b/setup.py @@ -36,6 +36,11 @@ 'Topic :: Multimedia :: Graphics', ], packages=find_packages(), - install_requires=['cffi>=0.6'], - extras_require={'xcb': ['xcffib']} + install_requires=['cffi>=1.1.0'], + setup_requires=['cffi>=1.1.0'], + cffi_modules=[ + 'cairocffi/ffi_build.py:ffi', + 'cairocffi/ffi_build.py:ffi_pixbuf' + ], + extras_require={'xcb': ['xcffib>=0.3.2']}, )