python-cairo+python-pygame work with default python in lenny?
tag 481506 patch
Hi,
apologies for lobbying for my pet peeves to be fixed in lenny, but the
attached python script (taking from upstream python-cairo 1.6.4[1],
needing python-pygame and python-cairo to be installed) works with
python 2.4 as is but not with the default python (2.5). Applying the
attached diff improves the situation making this also work with python
2.5. Some gory details below.
While the bug severity is set to "normal", the error message is somewhat
opaque and searching the internet only reveals some "maybe we should fix
this" comment, so the Debian user's experience might be improved by
eliminating the need for the search. If this is interesting enough for
people to upload and later unblock...
And here the promised gory details:
- The signature changes (insofar as they are changes) to Py_ssize_t are
from the python 2.5 documentation. For python 2.4 they are actually
no changes thanks to the cairo-private.h compatibility typedefs that
seem to be based on PEP 353[2].
- python-pygame uses PyObject_AsCharBuffer from the abstract buffer
protocol to get hold of the image buffer. This function seems to exist
since Python 1.6 (certainly does in 2.4), but only python 2.5 changes
is to actually use the charbufferproc that is now missing in
python-cairo.
- I don't know why pycairo upstream does not seem to have implemented
this despite adding tests that fail on python 2.5. Maybe they still
use python 2.4 only?
Kind regards
T.
1. http://webcvs.cairographics.org/pycairo/test/pygame-test1.py
2. http://www.python.org/dev/peps/pep-0353/
--
Thomas Viehmann, http://thomas.viehmann.net/
#!/usr/bin/env python
"""demonstrate pycairo and pygame
method1: use a pycairo and pygame directly
"""
import array
import math
import sys
import cairo
import pygame
def draw(surface):
x,y, radius = (250,250, 200)
ctx = cairo.Context(surface)
ctx.set_line_width(15)
ctx.arc(x, y, radius, 0, 2.0 * math.pi)
ctx.set_source_rgb(0.8, 0.8, 0.8)
ctx.fill_preserve()
ctx.set_source_rgb(1, 1, 1)
ctx.stroke()
def input(events):
for event in events:
if event.type == pygame.QUIT:
sys.exit(0)
else:
print event
Width, Height = 512, 512
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, Width, Height)
pygame.init()
window = pygame.display.set_mode( (Width,Height) )
screen = pygame.display.get_surface()
draw(surface)
#Create PyGame surface from Cairo Surface
buf = surface.get_data()
image = pygame.image.frombuffer(buf,(Width,Height),"ARGB",)
#Tranfer to Screen
screen.blit(image, (0,0))
pygame.display.flip()
while True:
input(pygame.event.get())
"""
with pycairo 1.4.12 and pygame 1.7.1 you get the error message:
Traceback (most recent call last):
File "./pygame-test1.py", line 42, in <module>
image = pygame.image.frombuffer(buf,(Width,Height),"ARGB",)
TypeError: char buffer type not available
This is because with
buf = surface.get_data()
pycairo provides a binary image buffer,
whereas with
image = pygame.image.frombuffer(buf,(Width,Height),"ARGB",)
pygame is expecting a text-based character buffer!
"""
diff -u pycairo-1.4.12/debian/changelog pycairo-1.4.12/debian/changelog
--- pycairo-1.4.12/debian/changelog
+++ pycairo-1.4.12/debian/changelog
@@ -1,3 +1,12 @@
+pycairo (1.4.12-1.2) unstable; urgency=low
+
+ * Non-maintainer upload.
+ * Python 2.5 compatibility of Image buffer interface.
+ (needed e.g. for interaction with python-pygame).
+ Closes: #481506
+
+ -- Thomas Viehmann <tv@beamnet.de> Tue, 13 Jan 2009 22:51:49 +0100
+
pycairo (1.4.12-1.1) unstable; urgency=low
* NMU.
only in patch2:
unchanged:
--- pycairo-1.4.12.orig/cairo/pycairo-surface.c
+++ pycairo-1.4.12/cairo/pycairo-surface.c
@@ -504,8 +504,8 @@
/* Buffer interface functions, used by ImageSurface.get_data() */
-static int
-image_surface_buffer_getreadbuf (PycairoImageSurface *o, int segment,
+static Py_ssize_t
+image_surface_buffer_getreadbuf (PycairoImageSurface *o, Py_ssize_t segment,
const void **ptr)
{
cairo_surface_t *surface = o->surface;
@@ -522,8 +522,8 @@
return height * stride;
}
-static int
-image_surface_buffer_getwritebuf (PycairoImageSurface *o, int segment,
+static Py_ssize_t
+image_surface_buffer_getwritebuf (PycairoImageSurface *o, Py_ssize_t segment,
const void **ptr)
{
cairo_surface_t *surface = o->surface;
@@ -540,25 +540,43 @@
return height * stride;
}
-static int
-image_surface_buffer_getsegcount (PycairoImageSurface *o, int *lenp)
+static Py_ssize_t
+image_surface_buffer_getsegcount (PycairoImageSurface *o, Py_ssize_t *lenp)
{
if (lenp) {
/* report the sum of the sizes (in bytes) of all segments */
cairo_surface_t *surface = o->surface;
int height = cairo_image_surface_get_height (surface);
int stride = cairo_image_surface_get_stride (surface);
- *lenp = height * stride;
+ *lenp = (Py_ssize_t) height * stride;
}
return 1; /* surface data is all in one segment */
}
+static Py_ssize_t
+image_surface_buffer_getcharbuf (PycairoImageSurface *o, Py_ssize_t segment,
+ const char **ptr)
+{
+ cairo_surface_t *surface = o->surface;
+ int height, stride;
+
+ if (segment != 0) {
+ PyErr_SetString(PyExc_SystemError,
+ "accessing non-existent ImageSurface segment");
+ return -1;
+ }
+ height = cairo_image_surface_get_height (surface);
+ stride = cairo_image_surface_get_stride (surface);
+ *ptr = (char *) cairo_image_surface_get_data (surface);
+ return height * stride;
+}
+
/* See Python C API Manual 10.7 */
static PyBufferProcs image_surface_as_buffer = {
(readbufferproc) image_surface_buffer_getreadbuf,
(writebufferproc)image_surface_buffer_getwritebuf,
(segcountproc) image_surface_buffer_getsegcount,
- (charbufferproc) NULL,
+ (charbufferproc) image_surface_buffer_getcharbuf,
};
static PyMethodDef image_surface_methods[] = {
Reply to: