All formats

pycairo

LanguagePython 3.10+
LicenseLGPL-2.1 or MPL-1.1
Repositorygithub.com/pygobject/pycairo
Documentationpycairo docs, surfaces reference
Depends onthe cairo C library (included in the Windows and macOS wheels)
Read / writeno / 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#