This article describes how to create text in Pycairo. You can find other topics in the main Pycairo article list.
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.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).select_font_face
selects an Arial font with default slant and weight (see below).move_to
sets the position for the textshow_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.
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:
cairo.FONT_SLANT_ITALIC
.cairo.FONT_WEIGHT_BOLD
.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:
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.
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)
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!
If you found this article useful, you might be interested in the book Computer Graphics in Python, or other books, by the same author.
<<PrevCopyright (c) Axlesoft Ltd 2020