@@ -68,6 +68,21 @@ def _fn_name(): return sys._getframe(1).f_code.co_name
68
68
BYTE_FORMAT = 1 # ARGB
69
69
70
70
71
+ class ArrayWrapper :
72
+ """Thin wrapper around numpy ndarray to expose the interface
73
+ expected by cairocffi. Basically replicates the
74
+ array.array interface.
75
+ """
76
+ def __init__ (self , myarray ):
77
+ self .__array = myarray
78
+ self .__data = myarray .ctypes .data
79
+ self .__size = len (myarray .flatten ())
80
+ self .itemsize = myarray .itemsize
81
+
82
+ def buffer_info (self ):
83
+ return (self .__data , self .__size )
84
+
85
+
71
86
class RendererCairo (RendererBase ):
72
87
fontweights = {
73
88
100 : cairo .FONT_WEIGHT_NORMAL ,
@@ -175,9 +190,25 @@ def draw_image(self, gc, x, y, im):
175
190
im = im [:, :, (2 , 1 , 0 , 3 )]
176
191
else :
177
192
im = im [:, :, (3 , 0 , 1 , 2 )]
178
- surface = cairo .ImageSurface .create_for_data (
179
- memoryview (im .flatten ()), cairo .FORMAT_ARGB32 , im .shape [1 ], im .shape [0 ],
180
- im .shape [1 ]* 4 )
193
+ if HAS_CAIRO_CFFI :
194
+ # cairocffi tries to use the buffer_info from array.array
195
+ # that we replicate in ArrayWrapper and alternatively falls back
196
+ # on ctypes to get a pointer to the numpy array. This works
197
+ # correctly on a numpy array in python3 but not 2.7. We replicate
198
+ # the array.array functionality here to get cross version support.
199
+ imbuffer = ArrayWrapper (im .flatten ())
200
+ else :
201
+ # py2cairo uses PyObject_AsWriteBuffer
202
+ # to get a pointer to the numpy array this works correctly
203
+ # on a regular numpy array but not on a memory view.
204
+ # At the time of writing the latest release version of
205
+ # py3cairo still does not support create_for_data
206
+ imbuffer = im .flatten ()
207
+ surface = cairo .ImageSurface .create_for_data (imbuffer ,
208
+ cairo .FORMAT_ARGB32 ,
209
+ im .shape [1 ],
210
+ im .shape [0 ],
211
+ im .shape [1 ]* 4 )
181
212
ctx = gc .ctx
182
213
y = self .height - y - im .shape [0 ]
183
214
0 commit comments