开罗FreeType字体 - 无效矩阵(不可逆)

时间:2015-12-27 12:47:53

标签: matrix fonts d cairo freetype

当我尝试在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 有什么问题?如何初始化矩阵?

1 个答案:

答案 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,手动创建缩放字体不是必需的,它可以从当前的字体面检索。