当我尝试在cairo中使用FT字体时遇到以下cairo错误:
无效矩阵(不可逆)
不涉及绘图,因为如果我使用玩具字体API来执行通常使用严格字体API的操作,那么它可以正常工作( cairo_scaled_font_text_to_glyphs 和 cairo_show_glyphs )。 所以问题肯定来自字体初始化的方式。
当我的画布获得 cairo_t 上下文时,这就是我设置字体的方式:
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 是对freetype加载器的调用,它返回来自此函数的内容:
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);
}
当没有注释初始化矩阵的代码时,我会在我的控制台中遇到一些cairo断言失败,例如
default_alignement:cairo-ft-font.c:657:_cairo_ft_unscaled_font_lock_face:断言`!unscaled-> from_face'失败。
fontToCairoData 有什么问题?如何初始化矩阵?
答案 0 :(得分:1)
问题是由于错误使用 cairo_save()和 cairo_restore()导致设置丢失(可能是默认字体矩阵)。
对于每个控件,先前的翻译保存并恢复如下:
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);
}
基于错误的假设,即保存/恢复仅对平面几何体产生影响。但这实际上破坏了几个设置。
当飞机正确恢复时:
void endControl(CustomControl ctrl)
{
cairo_translate(_cr, -ctrl.left, -ctrl.top);
if (ctrl.clipChildren)
cairo_reset_clip(_cr);
}
甚至不再需要与字体消失和矩阵相关的消息( cairo_set_font_size 完成工作),因为如上所述here,手动创建缩放字体不是必需的,它可以从当前的字体面检索。