[cairo] Funky text metrics

Keith Packard keithp at keithp.com
Sun Dec 19 19:13:35 PST 2004

I'm trying to uncover why text metrics are so scrambled in cairo and I've 
found at least part of the problem.

cairo computes the global font transformation by taking the font matrix and
mutiplying by the current transform matrix (ctm).  This matrix is then
decomposed into two separate pieces -- the x and y 'scale' factors and then
matrix holding the rest of the transformation (I believe this transform is
area preserving).

Within FreeType, these two factors are used in very different ways.  The x
and y scale factors are applied within the glyph loader itself as they are
required by all of the hinters.  The transformation matrix is applied after
the glyph is hinted but before the outline is rasterized.  The
transformation matrix is *not* used when computing overall font metrics.

Given the way cairo applies transforms to fonts, this overall tactic 
ensures that glyph shape is determined entirely by the pixel size of the 
glyph, without regard to any area preserving transforms (rotate, mirror or 

Now in looking at the font metrics functions, I see that the front-end/
back-end interface is defined to return all extents in device space; these
extents are then fed through the ictm to yield user space values.

This cannot work because all of the extent values are returned as scalars,
not vectors.  Any rotating, shearing or reflecting transform will have 
these values nicely scrambled.  A 90 degree rotation will set all of the 
vertical scalars to zero in the current implementation:

> autoimport Cairo;
> cr = new ();
> set_font (cr, "sans-12")
> set_matrix (cr, (matrix_t) { { 0, 1 }, { -1, 0 }, { 0, 0 } });
> current_font_extents (cr)
{ascent = 0, descent = 0, height = 0, max_x_advance = 0, max_y_advance = -16}

Obviously we have to let the back-end compute the user-space coordinates 
as the data structure doesn't have the ability to represent these vectors 
in device space.  I think this is possible, but performing the right 
conversion will be tricky as we have to separate out the effects of the 
font transform from the global transform.

The glyph metrics have similar issues.  The raw metrics returned
incorporate the x and y scale factors but ignore the transformation matrix.
The advance values respect both the scale factors and the transform matrix.
We should instead use the linearHoriAdvance/linearVertAdvance values which
ignore the transformation matrix.  Getting these back to user space should 
be the same as with the font extents above.

The alternative to using user-space across these APIs is to provide
vector-based extents structures, but that seems excessive.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
Url : http://lists.freedesktop.org/archives/cairo/attachments/20041219/2eeb5a7f/attachment.pgp

More information about the cairo mailing list