This example graphically shows the meaning of the logical bounding box of a pango line, as well as the difference in alignment between a PangoLayout and the corresponding PangoLayoutLine. It also illustrates how to go back and forth between pango and cairo coordinates.
1 //======================================================================
2 // Example that shows the relation between cairo coordinates and
3 // Pango coordinates.
4 //
5 // Dov Grobgeld <dov.grobgeld@gmail.com>
6 // Sat 2007-02-03 21:43
7 //
8 // This program is in the public domain
9 //
10 // Compile with:
11 //
12 // gcc `pkg-config --cflags --libs pangocairo` -o pango-bbox pango-bbox.c
13 //----------------------------------------------------------------------
14 #include <math.h>
15 #include <pango/pangocairo.h>
16
17 #define WIDTH 800
18 #define HEIGHT 300
19
20 // Returns the "depth" of a layout, that is the distance from the
21 // top of the layout to the baseline of the first line in the
22 // layout.
23 int get_layout_depth(PangoLayout *layout)
24 {
25 PangoLayoutLine *layout_line = pango_layout_get_line(layout,0);
26 PangoRectangle rect;
27
28 pango_layout_line_get_extents(layout_line,
29 NULL,
30 &rect);
31
32 return PANGO_ASCENT(rect);
33 }
34
35 static void
36 draw_text (cairo_t *cr,
37 const char *text)
38 {
39 PangoLayout *layout;
40 PangoLayoutLine *layout_line;
41 PangoFontDescription *desc;
42 PangoRectangle ink_rect, logical_rect;
43 int width, height;
44 double x, y;
45 double depth;
46
47 // Center coordinates on the middle of the region we are drawing
48 cairo_translate (cr, WIDTH/2, HEIGHT/2);
49
50 // Create a PangoLayout, set the font and text
51 layout = pango_cairo_create_layout (cr);
52
53 pango_layout_set_markup (layout, text, -1);
54 desc = pango_font_description_from_string ("Serif 70");
55 pango_layout_set_font_description (layout, desc);
56 pango_font_description_free (desc);
57
58 pango_layout_get_extents(layout,
59 &ink_rect,
60 &logical_rect);
61 x = -((double)logical_rect.width / PANGO_SCALE) / 2;
62 y = -((double)logical_rect.height / PANGO_SCALE) / 2;
63
64 // Draw a green point at the current x,y position
65 cairo_set_source_rgba (cr, 0.0, 1.0, 0.0, 0.5); // green
66 cairo_arc(cr,
67 x, y,
68 5, 0, 2*M_PI);
69 cairo_fill(cr);
70
71 // Draw the logical rectancgle
72 cairo_set_source_rgba (cr, 0.0, 0.0, 1.0, 0.5); // blue
73 cairo_rectangle(cr,
74 x+logical_rect.x/PANGO_SCALE,
75 y+logical_rect.y/PANGO_SCALE,
76 logical_rect.width/PANGO_SCALE,
77 logical_rect.height/PANGO_SCALE);
78 cairo_stroke(cr);
79
80 // Draw the depth line
81 depth = (double)get_layout_depth(layout);
82 cairo_set_source_rgba (cr, 0.5, 0.0, 0.5, 0.5);
83 cairo_move_to(cr, x, y+depth/PANGO_SCALE);
84 cairo_rel_line_to(cr, logical_rect.width/PANGO_SCALE, 0);
85 cairo_stroke(cr);
86
87 // Draw the text
88 cairo_move_to (cr, x, y+depth/PANGO_SCALE);
89 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); // black
90 pango_cairo_show_layout_line (cr, pango_layout_get_line(layout,0));
91
92 // Draw same text but with pango_cairo_show_layout
93 cairo_move_to (cr, x+1.2*logical_rect.width/PANGO_SCALE, y);
94 cairo_set_source_rgb (cr, 0.6, 0.6, 0.6); // grey
95 pango_cairo_show_layout (cr, layout);
96
97 /* free the layout object */
98 g_object_unref (layout);
99 }
100
101 int main (int argc, char **argv)
102 {
103 cairo_t *cr;
104 const char *filename = "pango-bbox.png";
105 cairo_surface_t *surface;
106
107 surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, WIDTH, HEIGHT);
108
109 cr = cairo_create (surface);
110
111 cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
112 cairo_paint (cr);
113 draw_text (cr,
114 "yd"
115 );
116 cairo_show_page (cr);
117 cairo_destroy (cr);
118
119 cairo_surface_write_to_png(surface, filename);
120
121 cairo_surface_destroy (surface);
122
123 return 0;
124 }
The resulting output: