Using Cairo in Pygame :: 29 Mar 2010

This is a method of using Cairo with Pygame. It works by sharing the same block of memory for the Cairo drawing surface and the Pygame image surface. The only trick to it is making sure that Cairo and Pygame use the same format to store the pixel data in.

#!/usr/bin/env python
import cairo
import pygame
import math

size = 400, 400

# Initialize pygame with 32-bit colors. This setting stores the pixels
# in the format 0x00rrggbb.
pygame.init()
screen = pygame.display.set_mode(size, 0, 32)

# Get a reference to the memory block storing the pixel data.
pixels = pygame.surfarray.pixels2d(screen)

# Set up a Cairo surface using the same memory block and the same pixel
# format (Cairo's RGB24 format means that the pixels are stored as
# 0x00rrggbb; i.e. only 24 bits are used and the upper 16 are 0).
cairo_surface = cairo.ImageSurface.create_for_data(
    pixels.data, cairo.FORMAT_RGB24, size[0], size[1])

# Draw a white circle to the screen using pygame.
radius = int(min(size)/2*0.7)
pos = [int(a/2) for a in size]
pygame.draw.circle(screen, (255,255,255), pos, radius)

# Draw a smaller black circle to the screen using Cairo.
context = cairo.Context(cairo_surface)
context.set_source_rgb(0, 0, 0)
context.arc(size[0]/2, size[1]/2, min(size)/2*0.5, 0, 2*math.pi)
context.fill()

# Flip the changes into view.
pygame.display.flip()

# Wait for the user to quit.
while pygame.QUIT not in [e.type for e in pygame.event.get()]:
    pass

Tested on Python 2.6.4, pycairo 1.8.6, Cairo 1.8.8, pygame 1.8.1, numpy 1.3.0.