Cairo FreeType 字体 - 无效矩阵(不可逆)
Cairo FreeType font - invalid matrix (not invertible)
我尝试在 cairo 中使用 FT 字体时遇到以下 cairo 错误:
invalid matrix (not invertible)
不涉及绘图,因为如果我使用玩具字体 API 来做通常使用严肃字体 API 所做的事情,那么它就可以工作 (cairo_scaled_font_text_to_glyphs 和 cairo_show_glyphs)。
所以问题肯定出在字体的初始化方式上。
这就是我在 canvas 获得 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 loader 的调用,它 returns 来自这个函数的东西:
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: Assertion `!unscaled->from_face' failed.
fontToCairoData 有什么问题?应该如何初始化矩阵?
问题是由于 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);
}
基于save/restore仅对平面几何有影响的错误假设。但这实际上破坏了几个设置。
飞机正常恢复时:
void endControl(CustomControl ctrl)
{
cairo_translate(_cr, -ctrl.left, -ctrl.top);
if (ctrl.clipChildren)
cairo_reset_clip(_cr);
}
与字体相关的消息消失了,甚至不再需要矩阵(cairo_set_font_size 完成了工作)因为,如前所述 here,不需要手动创建缩放字体,可以从当前字体中检索。
我尝试在 cairo 中使用 FT 字体时遇到以下 cairo 错误:
invalid matrix (not invertible)
不涉及绘图,因为如果我使用玩具字体 API 来做通常使用严肃字体 API 所做的事情,那么它就可以工作 (cairo_scaled_font_text_to_glyphs 和 cairo_show_glyphs)。 所以问题肯定出在字体的初始化方式上。
这就是我在 canvas 获得 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 loader 的调用,它 returns 来自这个函数的东西:
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: Assertion `!unscaled->from_face' failed.
fontToCairoData 有什么问题?应该如何初始化矩阵?
问题是由于 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);
}
基于save/restore仅对平面几何有影响的错误假设。但这实际上破坏了几个设置。
飞机正常恢复时:
void endControl(CustomControl ctrl)
{
cairo_translate(_cr, -ctrl.left, -ctrl.top);
if (ctrl.clipChildren)
cairo_reset_clip(_cr);
}
与字体相关的消息消失了,甚至不再需要矩阵(cairo_set_font_size 完成了工作)因为,如前所述 here,不需要手动创建缩放字体,可以从当前字体中检索。