pycairo
| Language | Python 3.10+ |
|---|---|
| License | LGPL-2.1 or MPL-1.1 |
| Repository | github.com/pygobject/pycairo |
| Documentation | pycairo docs, surfaces reference |
| Depends on | the cairo C library (included in the Windows and macOS wheels) |
| Read / write | no / yes (PostScript Level 2 and 3, EPS) |
pycairo exposes cairo’s drawing API to Python: paths, fills, strokes, gradients, text and images, on surfaces that write PNG, PDF, SVG or PostScript. A cairo.PSSurface produces a DSC-conforming PostScript file with embedded font subsets, one page per show_page() call.
cairo can’t read PostScript. Transparency is turned into embedded bitmaps in PostScript output. The coordinate origin is the top-left corner of the page, with y going down.
Installation#
Shell
pip install pycairo
Wheels for Windows and macOS include cairo. On Linux pip may build from source and needs the cairo headers (sudo apt install libcairo2-dev pkg-config python3-dev), or use the distribution package python3-cairo.
Basic usage: write a two-page PostScript file#
Python
import math
import cairo
WIDTH, HEIGHT = 595, 842 # A4 in points
with cairo.PSSurface("out.ps", WIDTH, HEIGHT) as surface:
ctx = cairo.Context(surface)
# page 1
ctx.select_font_face("Sans", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD)
ctx.set_font_size(24)
ctx.move_to(72, 72)
ctx.show_text("Hello, PostScript")
ctx.set_source_rgb(0.2, 0.4, 0.8)
ctx.rectangle(72, 120, 300, 150)
ctx.fill()
ctx.show_page()
# page 2
ctx.set_source_rgb(0.8, 0.1, 0.1)
ctx.set_line_width(4)
ctx.arc(WIDTH / 2, HEIGHT / 2, 100, 0, 2 * math.pi)
ctx.stroke()
ctx.show_page()
# leaving the "with" block finishes the surface and writes the trailer
How to set a different size for one page#
Python
surface.set_size(842, 595) # landscape A4; call before drawing the page
How to add a title and paper size (DSC comments)#
Python
surface = cairo.PSSurface("out.ps", 842, 1191)
surface.dsc_comment("%%Title: Quarterly report")
surface.dsc_begin_setup()
surface.dsc_comment("%%IncludeFeature: *MediaColor White")
surface.dsc_begin_page_setup()
surface.dsc_comment("%%IncludeFeature: *PageSize A3")
How to write PostScript Level 2#
Python
surface.restrict_to_level(cairo.PSLevel.LEVEL_2)
print(cairo.PSSurface.get_levels()) # levels this cairo build supports
How to write PostScript to memory#
PSSurface accepts any file-like object:
Python
import io
import cairo
buf = io.BytesIO()
with cairo.PSSurface(buf, 595, 842) as surface:
ctx = cairo.Context(surface)
ctx.move_to(72, 72)
ctx.show_text("in memory")
data = buf.getvalue() # bytes starting with b"%!PS-Adobe-3.0"
Tips#
surface.set_eps(True)writes Encapsulated PostScript; see pycairo for EPS.- Draw a PNG into the page with
cairo.ImageSurface.create_from_png("img.png")andctx.set_source_surface(img, x, y); ctx.paint().