c++ - FreeType 2 字符精确大小和精确位置

标签 c++ freetype

用ttf字体做了一些实验,并尝试使用著名的字体渲染库FreeType,版本2.5.3。

我的代码:

#include "ft2build.h"
#include FT_FREETYPE_H

#define FONTPATH "<font path here>"
const char* fontfile=FONTPATH "<fontname here>.TTF";
const int w=25;
const int h=25;
char* outbitmap;

int main() {
    outbitmap=new char[w*h];
    memset(outbitmap,0,w*h);
    FT_Library ftl;
    FT_Error err=FT_Init_FreeType(&ftl);
    FT_Face fface;
    err=FT_New_Face(ftl,fontfile,0,&fface);
    err=FT_Set_Pixel_Sizes(fface,w,h);
    FT_UInt ch;
    //ch=0x3042; //あ
    //ch='_';
    ch='|';
    FT_UInt chridx=FT_Get_Char_Index(fface,ch);
    err=FT_Load_Glyph(fface,chridx,FT_LOAD_DEFAULT);
    err=FT_Render_Glyph(fface->glyph,FT_RENDER_MODE_NORMAL);
    for(int y=0;y<fface->glyph->bitmap.rows;++y) {
        int outy=fface->glyph->bitmap.rows-fface->glyph->bitmap_top+y; //???how to get baseline position
        for(int x=0;x<fface->glyph->bitmap.width;++x) {
            int outx=fface->glyph->bitmap_left+x;
            outbitmap[outy*w+outx]=fface->glyph->bitmap.buffer[fface->glyph->bitmap.width*y+x];
        }
    }
    delete[] outbitmap;
    err=FT_Done_Face(fface);
    err=FT_Done_FreeType(ftl);
    return 0;
}

所以我有一些问题。 假设我需要在正确的位置将一个字符呈现为具有固定大小的字节数组。 字符大小必须正好适合输出位图中的大小,不允许裁剪。 完全忽略字距调整是可以的。

  1. 我指定字符 width=height=25。但是对于'|'它给出 fface->glyph->bitmap.rows==26。 对于任何普通字体,我应该如何设置高度以获得恰好 25px 的输出,而不是 26?如果不是 可能的话,有没有办法在之前以像素为单位精确计算输出字符高度 FT_Render_Glyph。 FT_Set_Pixel_Sizes 效果不佳,所以我有时会得到 +1px。

  2. 如何获得任何给定字体的基线位置?如果我有基线,我可以放置角色 在完全正确的位置。我没有 1000x1000 的屏幕,只有一个 25x25 的位图。

最佳答案

这太晚了,但我刚刚找到了如何做到这一点:

  1. (获取以像素为单位的字符高度)。据我了解,设置字体大小(例如使用 FT_Set_Char_Size)实际上只是定义了字体单位和像素单位之间的比例(this explains more)。即,72dpi 的 12pt 字体并不一定意味着字形为 12 像素高。但是,您可以获得一个边界框,我很确定它会包含所选字体中的每个字形。我就是这样做的:

    //12pt font
    double font_size = 12.0;   

    //Resolution means DPI here
    double pixel_size = font_size * resolution / 72; 

    //Font height and width in pixels
    int font_height = round((face->bbox.yMax - face->bbox.yMin)*pixel_size / face->units_per_EM);
    int font_width = round((face->bbox.xMax - face->bbox.xMin)*pixel_size / face->units_per_EM);

  1. 这就是我得到基线高度的方法。它只是任何字形基线以下的最大下降。当与上面的代码配对时,在此位置使用基线绘制字形应该保证所有字形都适合边界框。

    //Convert this to pixel_size if your DPI is not 72
    double font_size = 12.0;

    //Height in pixels (using a double for sub-pixel precision)
    double baseline_height = abs(face->descender) * font_size / face->units_per_EM;

(其中 face 是您加载的字体)。

编辑:忘记考虑 DPI,在我的应用程序中我只是使用 72,所以它取消了

关于c++ - FreeType 2 字符精确大小和精确位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24030488/

相关文章:

java - 将本地方法添加到 OpenJDK 源代码

C++文件输入流: reading "large" integers

c - libRocket 需要哪些 FreeType2 库模块?

linux - 尝试与 osgText 和 freetype 链接时出错

java - jpod 库在 eclipse 之外不工作

c# - 为什么会发生这种情况? (SharpFont/Monogame 错误)

c++ - 解构表达式

c++ - Qt moc.exe - 32 位和 64 位版本之间的区别?

c++ - 停止向下一个函数发送值

c++ - FreeType:如何栅格化非填充轮廓