I'm trying to use Freetype to render text for use in an SDL/framebuffer application running on a Raspberry Pi. This is what I'm seeing at the moment:
See the '0' and '1' in 2015? They are too close together. Looks wrong.
My code that draws the text into an image buffer:
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;
}
}
}
}
}
The kerning doesn't seem to make any difference with any of the modes I supply. (kerning.x is always 0)
What am I doing wrong here?
The problem is that I wasn't accounting for the bitmap_top and bitmap_left adjustments in the glyph structure.
After I calculate the Px and Py position I added this snippit of code:
if (Fnt->glyph->format == FT_GLYPH_FORMAT_BITMAP)
{
Px += Fnt->glyph->bitmap_left;
Py = (AscentF >> FShift) - Fnt->glyph->bitmap_top;
}
And now the '1' has moved into place correctly. This is what it looks like now: