为什么 Freetype 渲染的字符靠得太近?

Why does Freetype render characters too close together?

我正在尝试使用 Freetype 渲染文本,以便在 Raspberry Pi 上的 SDL/framebuffer 应用程序 运行 中使用。这就是我目前看到的:

看到 2015 年的“0”和“1”了吗?他们靠得太近了。看起来不对。

我将文本绘制到图像缓冲区的代码:

int FScale = 64;
int FShift = 6;
GArray<uint32> Glyphs;
for (OsChar *s = Str; *s; s++)
{
    FT_UInt index = FT_Get_Char_Index(Fnt, *s);
    if (index)
        Glyphs.Add(index);
}

// Measure the string...
GdcPt2 Sz;
int FontHt = Font->GetHeight();
int AscentF = (int) (Font->Ascent() * FScale);
int LoadMode = FT_LOAD_FORCE_AUTOHINT;
for (unsigned i=0; i<Glyphs.Length(); i++)
{
    error = FT_Load_Glyph(Fnt, Glyphs[i], LoadMode);
    if (error == 0)
    {
        int PyF = AscentF - Fnt->glyph->metrics.horiBearingY;

        Sz.x += Fnt->glyph->metrics.horiAdvance;
        Sz.y = max(Sz.y, PyF + Fnt->glyph->metrics.height);
    }
}

// Create the memory context to draw into
x = ((Sz.x + FScale - 1) >> FShift) + 1;
y = FontHt;

if (Img.Reset(new GMemDC(x, y, CsIndex8)))
{
    // Clear the context to black
    Img->Colour(0);
    Img->Rectangle();

    int CurX = 0;
    int FBaseline = Fnt->size->metrics.ascender;
    for (unsigned i=0; i<Glyphs.Length(); i++)
    {
        error = FT_Load_Glyph(Fnt, Glyphs[i], LoadMode);
        if (error == 0)
        {
            error = FT_Render_Glyph(Fnt->glyph, FT_RENDER_MODE_NORMAL);
            if (error == 0)
            {
                FT_Bitmap &bmp = Fnt->glyph->bitmap;
                if (bmp.buffer)
                {
                    int Px = (CurX + (FScale >> 1)) >> FShift;
                    int PyF = AscentF - Fnt->glyph->metrics.horiBearingY;
                    int Py = PyF >> FShift;

                    // copy bitmap into my image buffer at 'Px' x pos
                }

                if (i < Glyphs.Length() - 1)
                {
                    FT_Vector kerning;
                    FT_Get_Kerning(Fnt, Glyphs[i], Glyphs[i+1], FT_KERNING_DEFAULT, &kerning);
                    CurX += Fnt->glyph->metrics.horiAdvance + kerning.x;
                }
                else
                {
                    CurX += Fnt->glyph->metrics.horiAdvance;
                }
            }
        }
    }
}

字距调整似乎与我提供的任何模式没有任何区别。 (kerning.x 始终为 0)

我做错了什么?

问题是我没有考虑字形结构中的 bitmap_top 和 bitmap_left 调整。

在计算 Px 和 Py 位置后,我添加了这段代码:

if (Fnt->glyph->format == FT_GLYPH_FORMAT_BITMAP)
{
    Px += Fnt->glyph->bitmap_left;
    Py = (AscentF >> FShift) - Fnt->glyph->bitmap_top;
}

现在“1”已正确移动到位。这是现在的样子: