当我尝试将字体设置为24号时,由于字体高度设置不正确,缓冲区溢出。无论我指定什么大小,它都保持在17。我想念什么?我正在使用bindbc.freetype。
该代码在字体大小为12和14的情况下效果很好。在libfreetype中获取字体高度(像素)的正确方法是什么?我已经尝试过上升-以及下降。
module textrenderer;
import bindbc.freetype;
/// return value of text rendering
struct RenderedText
{
/// dimensions
uint width, height;
/// data
uint[] bitmap;
}
/// thrown when font loading fails
class FontLoadException : Exception
{
/// constructor
this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable nextInChain = null)
pure nothrow @nogc @safe
{
super(msg, file, line, nextInChain);
}
}
/// renders text as an array of unsigned ints
class TextRenderer
{
/// initializes freetype
static bool initialize()
{
/// load Freetype library
immutable ret = loadFreeType();
if(ret != ftSupport)
{
return false;
}
if(FT_Init_FreeType(&library_))
{
return false;
}
return true;
}
/// cleanup
static void shutdown()
{
foreach(value ; fonts_)
{
destroy(value);
}
fonts_ = null;
FT_Done_FreeType(library_);
}
/// load a font
static void loadFont(const string name, const string path, uint size)
{
fonts_[name] = new Font(path, size);
}
/// render RGBA texture of text
static RenderedText renderText(const string fontName, const wstring text, ubyte r=0xff, ubyte g=0xff, ubyte b=0xff)
{
import std.stdio: writefln, writef;
RenderedText rt;
if(fontName !in fonts_)
return rt;
Font font = fonts_[fontName];
getSize(font, text, rt.width, rt.height);
rt.bitmap = new uint[rt.width * rt.height];
rt.bitmap[] = r | g << 8 | b << 16;
int x=0;
writefln("rt.size: %s, %s", rt.width, rt.height);
writefln("The font ascent and descent are %s, %s", font.face_.ascender >> 6, font.face_.descender >> 6);
immutable baseline = (font.face_.ascender >> 6);
foreach(ch ; text)
{
FT_Load_Char(font.face_, ch, FT_LOAD_RENDER);
writefln("The bitmap_top of `%s` is %s", ch, font.face_.glyph.bitmap_top);
writefln(" The x,y bearing is %s, %s", font.face_.glyph.metrics.horiBearingX >> 6,
font.face_.glyph.metrics.horiBearingY >> 6 );
writefln(" The height is %s", font.face_.glyph.metrics.height >> 6);
for(int row=0; row < font.face_.glyph.bitmap.rows; ++row)
{
immutable YPOS = rt.height - (row + (baseline - font.face_.glyph.bitmap_top)) - 1;
for(int col=0; col < font.face_.glyph.bitmap.pitch; ++col)
{
immutable XPOS = x + col;
writefln("`%s`: XPOS,YPOS=%s,%s", ch, XPOS, YPOS);
rt.bitmap[XPOS + YPOS * rt.width] |=
font.face_.glyph.bitmap.buffer[col + row * font.face_.glyph.bitmap.width] << 24;
}
}
x += (font.face_.glyph.advance.x >> 6);
}
return rt;
}
private static getSize(Font font, const wstring text, ref uint width, ref uint height)
{
import std.stdio : writefln;
import std.algorithm : max;
width = 0;
writefln("The font ascent - descent is %s", (font.face_.ascender - font.face_.descender)>>6);
height = cast(uint)(font.face_.height >> 6);
foreach(ch ; text)
{
FT_Load_Char(font.face_, ch, FT_LOAD_RENDER);
width += cast(uint)(font.face_.glyph.advance.x >> 6);
}
}
package static FT_Library library_;
private static Font[string] fonts_;
}
private class Font
{
this(const string path, uint fontSize)
{
import std.string: toStringz;
immutable error = FT_New_Face(TextRenderer.library_, path.toStringz, 0, &face_);
if(error != 0)
{
throw new FontLoadException("Failed to load font `" ~ path ~ "`");
}
FT_Set_Pixel_Sizes(face_, 0, fontSize);
}
~this()
{
FT_Done_Face(face_);
}
package FT_Face face_;
}
当我尝试使用其他TTF字体文件时,此问题消失了。但是我仍然遇到缓冲区溢出的问题,因此计算错误。
例如,当renderText试图写入0.42作为第一个像素时,它计算的高度为40。我不知道如何计算我需要的额外3。
另外,有时当我在更改所使用的字体大小后重新编译时,它仍然与以前一样。有点不对劲。