[cairo] Font extents mysteries

Tim Teulings rael at edge.ping.de
Wed May 9 13:45:43 PDT 2007


Hello!

I'm having some strange effects with font extents using the Toy API
under X11.

What I'm doing?
I'm creating a cairo_scaled_font_t by first selecting a font face

cairo_select_font_face(cairo,name.c_str(),
                               CAIRO_FONT_SLANT_NORMAL,
                               CAIRO_FONT_WEIGHT_NORMAL);

where name is an std::string containing a font name like "Nimbus Sans L".

After that I do something like:

options=cairo_font_options_create();

fontScaled=cairo_scaled_font_create(cairo_get_font_face(cairo),&scaleMatrix,&transformMatrix,options);

cairo_font_options_destroy(options);			

Where scaleMatrix is initialized using cairo_matrix_init_scale to sclae
the font in horizontal and vertical dirction by the same factor
(pixelHeight*DPI) and transformMatrix is the result of cairo_get_matrix
(I never explicitly change the default matrix).

The resulting cairo_scaled_font_t is stored for later use.

Later on I calculate the bounds of a text string by doing something like


cairo_scaled_font_text_extents(fontScaled,buffer.c_str(),&textents);

where buffer is the std::string in question.

After that I calculate the horizontal bounds by assuming that

left=int(ceil(textents.x_bearing));
right=int(ceil(textents.x_advance-textents.width-textents.x_bearing));
width=size_t(ceil(textents.x_advance));

where "left" is the space between origin and the first pixel of the
first character, "right" is the space after the last letter and "width"
is the overall size of the string (including the amounts for left and
right). The resulting horizontal bounding box would then be something like:

<"left" pixel nothing"><real displayed text of width "width"><"right"
pixel nothing>

Based on this I later on draw the string in a X11 window by doing

        cairo_save(cairo);
        cairo_set_scaled_font(cairo,fontScaled);

        cairo_move_to(cairo,x,y);
        cairo_show_text(cairo,b.c_str());
        cairo_stroke(cairo);

        cairo_restore(cairo);

(b again is a std::string holding the text in question)

I also use the values of the text extents to draw a grid marking the
bounds of the text. The problem is, that the text exactly fits the grid
in *most* cases - but not for all!

Something like "Homtitompti" or "Illumination" works, but "Günther",
"Geld" or "d" does not. In the case where the bounds do not exactly
match the last letter extents is bounding box to the right filling the
space claimed to be reserved for space after the last letter by one or
even two pixel. The starting pixel (that means the value of "left")
however always seems to match exactly. I'm using an effective pixel
height for the font of 52 pixel.

Am I doing something wrong? Is there an error in my code or am I basing
by code on wrong assumptions?

-- 
Gruß...
       Tim



More information about the cairo mailing list