为什么 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”已正确移动到位。这是现在的样子:
我正在尝试使用 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”已正确移动到位。这是现在的样子: