Perl Cairo tutorial - Text dimensions

This is one page of a Perl Cairo tutorial.

This shows getting the extent of text using text_extents, and using the dimensions of the text to centre the text in the image. The red line in the image demonstrates the various dimensions of the text. A new function, set_source_rgba, sets both the colour of the line and its transparency.
use warnings;
use strict;
use Cairo;
my $size = 400;
my $surface = Cairo::ImageSurface->create ('argb32', $size, $size);
my $cr = Cairo::Context->create ($surface);
$cr->rectangle (0, 0, $size, $size);
# Colour scheme courtesy of
$cr->set_source_rgb (0xe8/0xff, 1, 0);
$cr->fill ();
# Draw a grid
$cr->set_source_rgb (0.4, 0.7, 0.4);
$cr->set_line_width (2);
for my $i (1..3) {
    $cr->move_to (($size * $i)/4, 0);
    $cr->line_to (($size * $i)/4, $size);
    $cr->move_to (0, ($size * $i)/4);
    $cr->line_to ($size, ($size * $i)/4);
$cr->stroke ();

# Draw the text at an offset of 1/4 the size of the image from the top
# left, and then draw the boundaries of the text using the return
# value from text_extents.

$cr->set_source_rgb (0.3, 0.3, 0.3);
$cr->select_font_face ('Utopia', 'normal', 'normal');
$cr->set_font_size ($size/4);
my $text = "Larry";
# Get the size of the text. This is a hash reference.
my $extents = $cr->text_extents ($text);
# Print out the text extents.
for my $k (keys %$extents) {
    print "$k: $extents->{$k}\n";
$cr->move_to ($size/4, $size/4);
$cr->show_text ($text);
$cr->fill ();

# Draw the red lines around the text to demonstrate the meaning of the
# extents.

$cr->set_source_rgba (1, 0, 0, 0.5);
$cr->set_line_width (5);
my $xb = $size/4 + $extents->{x_bearing};
my $yb = $size/4 + $extents->{y_bearing};
$cr->move_to ($xb, $size/4);
$cr->line_to ($xb, $yb);
my $xa = $size/4 + $extents->{x_advance};
$cr->line_to ($xa, $yb);
my $yh = $size/4 + $extents->{y_bearing} + $extents->{height};
$cr->line_to ($xa, $yh);
$cr->line_to ($xb, $yh);
$cr->stroke ();

# Now get how to centre the text.

$cr->set_source_rgb (0, 0, 0);
# Centre the text in the x direction.
my $xc = $size/2 - ($extents->{x_advance} + $extents->{x_bearing})/2;
# Go down all of y_bearing, then back up half the height to centre the
# text in the y direction.
my $yc = $size/2 - $extents->{y_bearing} - $extents->{height}/2;
$cr->move_to ($xc, $yc);
$cr->show_text ($text);
$cr->fill ();

my $png = 'centred-text.png';
$surface->write_to_png ($png);


Copyright © Ben Bullock 2009-2023. All rights reserved. For comments, questions, and corrections, please email Ben Bullock ( or use the discussion group at Google Groups. / Privacy / Disclaimer