字体大小增加时,libfreetype字体信息不正确

当我尝试将字体设置为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_;
}

评论
gcum
gcum

当我尝试使用其他TTF字体文件时,此问题消失了。但是我仍然遇到缓冲区溢出的问题,因此计算错误。

例如,当renderText试图写入0.42作为第一个像素时,它计算的高度为40。我不知道如何计算我需要的额外3。

另外,有时当我在更改所使用的字体大小后重新编译时,它仍然与以前一样。有点不对劲。

点赞
评论