This article is part of a series on Pycairo.

This article describes how to create text in Pycairo. You can find other topics in the main Pycairo article list.

Drawing a simple text string

Here is the code to create a simple text string in our user coordinates (see the previous article). The full code is here:

import cairo WIDTH = 3 HEIGHT = 2 PIXEL_SCALE = 200 surface = cairo . ImageSurface ( cairo . FORMAT_RGB24 , WIDTH * PIXEL_SCALE , HEIGHT * PIXEL_SCALE ) ctx = cairo . Context ( surface ) ctx . scale ( PIXEL_SCALE , PIXEL_SCALE ) ctx . rectangle ( 0 , 0 , WIDTH , HEIGHT ) ctx . set_source_rgb ( 0.8 , 0.8 , 1 ) ctx . fill () # Drawing code ctx . set_source_rgb ( 1 , 0 , 0 ) ctx . set_font_size ( 0.25 ) ctx . select_font_face ( "Arial" , cairo . FONT_SLANT_NORMAL , cairo . FONT_WEIGHT_NORMAL ) ctx . move_to ( 0.5 , 0.5 ) ctx . show_text ( "Drawing text" ) # End of drawing code surface . write_to_png ( 'text.png' )

Within the drawing code:

set_source_rgb sets the colour to red.

sets the colour to red. set_font_size sets the text size to 0.25 units. This gives the approximate text height (the overall page size is 2 by 3 units).

sets the text size to 0.25 units. This gives the approximate text height (the overall page size is 2 by 3 units). select_font_face selects an Arial font with default slant and weight (see below).

selects an Arial font with default slant and weight (see below). move_to sets the position for the text

sets the position for the text show_text displays the text using the style, colour and position specified.

Here is the result:

The font size is specified in units (depending on the current scaling). If we assume that our units represent inches, the font height would be 0.25 inches. To convert this to points, you multiply it by 72 (a point is 1/72 of an inch), so our font would be 18 pt if we printed the image above at 3 by 2 inches.

Font styles

We will now change the drawing code to try some different font styles:

ctx . set_source_rgb ( 1 , 0 , 0 ) ctx . set_font_size ( 0.25 ) ctx . select_font_face ( "Arial" , cairo . FONT_SLANT_NORMAL , cairo . FONT_WEIGHT_NORMAL ) ctx . move_to ( 0.5 , 0.4 ) ctx . show_text ( "Arial" ) ctx . select_font_face ( "Arial" , cairo . FONT_SLANT_ITALIC , cairo . FONT_WEIGHT_NORMAL ) ctx . move_to ( 0.5 , 0.7 ) ctx . show_text ( "Arial italic" ) ctx . select_font_face ( "Arial" , cairo . FONT_SLANT_NORMAL , cairo . FONT_WEIGHT_BOLD ) ctx . move_to ( 0.5 , 1.0 ) ctx . show_text ( "Arial bold" ) ctx . select_font_face ( "Times" , cairo . FONT_SLANT_NORMAL , cairo . FONT_WEIGHT_NORMAL ) ctx . move_to ( 0.5 , 1.3 ) ctx . show_text ( "Times" ) ctx . select_font_face ( "Courier" , cairo . FONT_SLANT_NORMAL , cairo . FONT_WEIGHT_NORMAL ) ctx . move_to ( 0.5 , 1.6 ) ctx . show_text ( "Courier" )

We keep the size and colour the same, and display 5 lines of text with different settings:

Normal Arial text. Arial italic, by setting the font face to use cairo.FONT_SLANT_ITALIC . Arial bold, by setting the font face to use cairo.FONT_WEIGHT_BOLD . Times font, by changing the font face. Courier font, by changing the font face.

In each case we add 0.3 to the y position in the move_to call, to move each line below the previous. Here is the result:

Text metrics

It is often useful to know how large the text will be when it is displayed on the page. This is easy to find using the text_extents function:

xbearing , ybearing , width , height , dx , dy = ctx . text_extents ( s )

text_extents returns a tuple containing 6 values that describe the dimensions of the text. The dimensions are calculated using the selected font and current scaling factor.

In the code above the tuple is unpacked into 6 variables. We are only interested in the width and height for now. These specify the width and height of a rectangle than tightly contains all the pixels that will be marked when the text is displayed.

We will look at the other text metrics later in a later article.

Example - text alignment

Let's start by printing 3 lines of text:

xpos = 0.5 ctx . set_source_rgb ( 0 , 0 , 0 ) ctx . set_font_size ( 0.20 ) ctx . select_font_face ( "Arial" , cairo . FONT_SLANT_NORMAL , cairo . FONT_WEIGHT_NORMAL ) ctx . move_to ( xpos , 0.7 ) ctx . show_text ( "Text string" ) ctx . move_to ( xpos , 1.0 ) ctx . show_text ( "Longer text string" ) ctx . move_to ( xpos , 1.3 ) ctx . show_text ( "Even longer text string" )

This will display the text, left aligned (because each move_to has the same x coordinate, 0.5)

Now we are going to right align the text.

xpos = 2.5 ctx . set_source_rgb ( 0 , 0 , 0 ) ctx . set_font_size ( 0.20 ) ctx . select_font_face ( "Arial" , cairo . FONT_SLANT_NORMAL , cairo . FONT_WEIGHT_NORMAL ) s = "Text string" xbearing , ybearing , width , height , dx , dy = ctx . text_extents ( s ) ctx . move_to ( xpos - width , 0.7 ) ctx . show_text ( s ) s = "Longer text string" xbearing , ybearing , width , height , dx , dy = ctx . text_extents ( s ) ctx . move_to ( xpos - width , 1.0 ) ctx . show_text ( s ) s = "Even longer text string" xbearing , ybearing , width , height , dx , dy = ctx . text_extents ( s ) ctx . move_to ( xpos - width , 1.3 ) ctx . show_text ( s )

Notice that we have set xpos to 2.5. We will align the right edge of each string with that position.

For each of the three strings, we use text_extents to calculate the metrics, including the width of the string. We then set the x position to xpos - width in the move_to call. This means that each string has a different x position, that has been calculated to that its right hand edge is at x = 2.5 . Here is the result:

If you wanted to centre align the text, you should use xpos - width/2 as the x position (setting xpos to something suitable, for instance 1.5)

Text paths

You can convert a text string to a path. Once you have the path you can fill it (that will look similar to just displaying text the normal way), or outline it, or both.

Here is how to outline some text:

ctx . set_source_rgb ( 1 , 0 , 0 ) ctx . set_font_size ( 0.75 ) ctx . select_font_face ( "Arial" , cairo . FONT_SLANT_NORMAL , cairo . FONT_WEIGHT_NORMAL ) ctx . move_to ( 0.3 , 1.5 ) ctx . text_path ( "Outline" ) ctx . set_line_width ( 0.02 ) ctx . stroke ()

All we have done here is call text_path instead of show_text . This adds the text letter shapes to the path. We then set the line width and stroke the path. We have made the text quite large so you can see the effect.

You can combine the text path with other shapes:

ctx . set_source_rgb ( 1 , 0 , 0 ) ctx . set_font_size ( 0.75 ) ctx . select_font_face ( "Arial" , cairo . FONT_SLANT_NORMAL , cairo . FONT_WEIGHT_NORMAL ) ctx . rectangle ( 0.2 , 0.8 , 2.6 , 1 ) ctx . move_to ( 0.3 , 1.5 ) ctx . text_path ( "Outline" ) ctx . set_fill_rule ( cairo . FILL_RULE_EVEN_ODD ) ctx . fill ()

In this case, we have create a rectangle, with text inside it. The rectangle and text form part of the same path. When we fill it with the even-odd fill rule, we get text shaped holes in the rectangle!

See also

If you found this article useful you might be interested in my ebook Computer Graphics in Python.

Previous

Next

Tag cloud

2d arrays

abstract data type

alignment

and

array

arrays

bezier curve

built-in function

close

closure

colour

comparison operator

comprehension

context

conversion

data types

design pattern

device space

dictionary

duck typing

efficiency

encryption

enumerate

filter

font

font style

for loop

function

function composition

function plot

functools

generator

gif

gradient

higher order function

html

image processing

imagesurface

immutable object

index

inner function

input

installing

iter

iterator

itertools

lambda function

len

linspace

list

list comprehension

logical operator

lru_cache

mandelbrot

map

monad

mutability

named parameter

numeric python

numpy

object

open

operator

optional parameter

or

partial application

path

positional parameter

print

pure function

radial gradient

range

recursion

reduce

rotation

scaling

sequence

slice

slicing

sound

spirograph

str

stream

string

subpath

symmetric encryption

template

text

text metrics

transform

translation

transparency

tuple

unpacking

user space

vectorisation

webserver

website

while loop

zip