Reputation: 1921
I encounter the following cairo error when I try to use a FT font in cairo:
invalid matrix (not invertible)
Drawing is not involved because if I use the toy font API to do what is usually done with the serious font API then it works (cairo_scaled_font_text_to_glyphs and cairo_show_glyphs). So the problem certainly comes from the way the font is initialized.
This is how I set the font when my canvas gets a cairo_t context:
void fontToCairoData()
{
_fontOptions = cairo_font_options_create;
cairo_get_font_options (_cr, _fontOptions);
/*
- Toy API w/o matrix init: seconds assert fails: invalid matrix (not invertible)
- Toy API + matrix init: OK
- FreeType loader w/o matrix init: second assert fails: invalid matrix (not invertible)
- FreeType loader + matrix init: the two assert OK but internal cairo assert failure.
*/
cairo_matrix_init(&_fontMat, _font.size, 0, 0, _font.size, 0, 0);
cairo_matrix_init(&_fontCtm, _font.size, 0, 0, _font.size, 0, 0);
cairo_font_face_t* ff;
version(none) // toy API
{
cairo_select_font_face(_cr, "Sans", CairoFontSlant.Normal, CairoFontWeight.Normal);
ff = cairo_get_font_face(_cr);
}
else ff = getCairoFont(_font.name);
assert(cairo_font_face_status(ff) == CairoStatus.Success,
cairo_font_face_status(ff).cairo_status_to_string.fromStringz);
cairo_ft_font_face_set_synthesize(ff, _font.getStyles.container & 3);
_sf = cairo_scaled_font_create(ff, &_fontMat, &_fontCtm, _fontOptions);
assert(cairo_scaled_font_status(_sf) == CairoStatus.Success,
cairo_scaled_font_status(_sf).cairo_status_to_string.fromStringz);
cairo_set_scaled_font(_cr, _sf);
}
getCairoFont is a call to the freetype loader, it returns something that comes from this function:
cairo_font_face_t* createFont(string name)
{
import std.string: toStringz;
FT_Face ftFace;
FT_New_Face(ftHandle, cast(char*)name.toStringz, 0, &ftFace);
return cairo_ft_font_face_create_for_ft_face(ftFace, 0);
}
When the code that initializes the matrices is not commented, I get in my console some cairo assertion failures such as
default_alignement: cairo-ft-font.c:657: _cairo_ft_unscaled_font_lock_face: Assertion `!unscaled->from_face' failed.
What's wrong in fontToCairoData ? How should the matrices be initialized ?
Upvotes: 1
Views: 1403
Reputation: 1921
The problem was caused by a wrong usage of cairo_save() and cairo_restore() that caused settings to be lost (probably the default font matrix).
For each control, the previous translation was saved and restored like this:
void beginControl(CustomControl ctrl)
{
cairo_save(_cr);
cairo_translate(_cr, ctrl.left, ctrl.top);
if (ctrl.clipChildren)
{
cairo_rectangle(_cr, -1, -1, ctrl.width+2, ctrl.height+2);
cairo_clip(_cr);
}
}
void endControl()
{
cairo_restore(_cr);
}
Based on the wrong assumption that save/restore has only an effect on the plane geometry. But this was actually corrupting several settings.
When the plane is properly restored:
void endControl(CustomControl ctrl)
{
cairo_translate(_cr, -ctrl.left, -ctrl.top);
if (ctrl.clipChildren)
cairo_reset_clip(_cr);
}
The messages related to the fonts disapear and the matrices are even not needed anymore (cairo_set_font_size does the job) because, as mentioned here, to create manually a scaled font is not necessary, it can be retrieved from the current font face.
Upvotes: 1