Skip to main content
`Ctrl`+`K`

# Cairo Integration

Despite cairo not being a GObject based library, PyGObject provides special cairo integration through pycairo. Functions returning and taking cairo data types get automatically converted to pycairo objects and vice versa.

Some distros ship the PyGObject cairo support in a separate package. If you’ve followed the instructions on “Getting Started” you should have everything installed.

If your application requires the cairo integration you can use `gi.require_foreign()`:

    try:
        gi.require_foreign("cairo")
    except ImportError:
        print("No pycairo integration :(")

Note that PyGObject currently does not support cairocffi, only pycairo.

## Demo

The following example shows a `Gtk.Window` with a custom drawing in Python using pycairo.

      1#!/usr/bin/env python3
      2"""Based on cairo-demo/X11/cairo-demo.c."""
      3
      4import cairo
      5import gi
      6
      7gi.require_version("Gtk", "4.0")
      8from gi.repository import Gtk
      9
     10SIZE = 30
     11
     12
     13class Application(Gtk.Application):
     14    def do_activate(self):
     15        window = Gtk.ApplicationWindow(
     16            application=self, default_width=450, default_height=600
     17        )
     18
     19        drawing_area = Gtk.DrawingArea()
     20        drawing_area.set_draw_func(self.draw)
     21        window.set_child(drawing_area)
     22
     23        window.present()
     24
     25    def triangle(self, ctx):
     26        ctx.move_to(SIZE, 0)
     27        ctx.rel_line_to(SIZE, 2 * SIZE)
     28        ctx.rel_line_to(-2 * SIZE, 0)
     29        ctx.close_path()
     30
     31    def square(self, ctx):
     32        ctx.move_to(0, 0)
     33        ctx.rel_line_to(2 * SIZE, 0)
     34        ctx.rel_line_to(0, 2 * SIZE)
     35        ctx.rel_line_to(-2 * SIZE, 0)
     36        ctx.close_path()
     37
     38    def bowtie(self, ctx):
     39        ctx.move_to(0, 0)
     40        ctx.rel_line_to(2 * SIZE, 2 * SIZE)
     41        ctx.rel_line_to(-2 * SIZE, 0)
     42        ctx.rel_line_to(2 * SIZE, -2 * SIZE)
     43        ctx.close_path()
     44
     45    def inf(self, ctx):
     46        ctx.move_to(0, SIZE)
     47        ctx.rel_curve_to(0, SIZE, SIZE, SIZE, 2 * SIZE, 0)
     48        ctx.rel_curve_to(SIZE, -SIZE, 2 * SIZE, -SIZE, 2 * SIZE, 0)
     49        ctx.rel_curve_to(0, SIZE, -SIZE, SIZE, -2 * SIZE, 0)
     50        ctx.rel_curve_to(-SIZE, -SIZE, -2 * SIZE, -SIZE, -2 * SIZE, 0)
     51        ctx.close_path()
     52
     53    def draw_shapes(self, ctx, x, y, fill):
     54        ctx.save()
     55
     56        ctx.new_path()
     57        ctx.translate(x + SIZE, y + SIZE)
     58        self.bowtie(ctx)
     59        if fill:
     60            ctx.fill()
     61        else:
     62            ctx.stroke()
     63
     64        ctx.new_path()
     65        ctx.translate(3 * SIZE, 0)
     66        self.square(ctx)
     67        if fill:
     68            ctx.fill()
     69        else:
     70            ctx.stroke()
     71
     72        ctx.new_path()
     73        ctx.translate(3 * SIZE, 0)
     74        self.triangle(ctx)
     75        if fill:
     76            ctx.fill()
     77        else:
     78            ctx.stroke()
     79
     80        ctx.new_path()
     81        ctx.translate(3 * SIZE, 0)
     82        self.inf(ctx)
     83        if fill:
     84            ctx.fill()
     85        else:
     86            ctx.stroke()
     87
     88        ctx.restore()
     89
     90    def fill_shapes(self, ctx, x, y):
     91        self.draw_shapes(ctx, x, y, True)
     92
     93    def stroke_shapes(self, ctx, x, y):
     94        self.draw_shapes(ctx, x, y, False)
     95
     96    def draw(self, da, ctx, width, height):
     97        ctx.set_source_rgb(0, 0, 0)
     98
     99        ctx.set_line_width(SIZE / 4)
    100        ctx.set_tolerance(0.1)
    101
    102        ctx.set_line_join(cairo.LINE_JOIN_ROUND)
    103        ctx.set_dash([SIZE / 4.0, SIZE / 4.0], 0)
    104        self.stroke_shapes(ctx, 0, 0)
    105
    106        ctx.set_dash([], 0)
    107        self.stroke_shapes(ctx, 0, 3 * SIZE)
    108
    109        ctx.set_line_join(cairo.LINE_JOIN_BEVEL)
    110        self.stroke_shapes(ctx, 0, 6 * SIZE)
    111
    112        ctx.set_line_join(cairo.LINE_JOIN_MITER)
    113        self.stroke_shapes(ctx, 0, 9 * SIZE)
    114
    115        self.fill_shapes(ctx, 0, 12 * SIZE)
    116
    117        ctx.set_line_join(cairo.LINE_JOIN_BEVEL)
    118        self.fill_shapes(ctx, 0, 15 * SIZE)
    119        ctx.set_source_rgb(1, 0, 0)
    120        self.stroke_shapes(ctx, 0, 15 * SIZE)
    121
    122
    123app = Application()
    124app.run()