FreeType 2字符确切大小和确切位置

时间:2014-06-04 06:28:10

标签: 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. 我指定了字符宽度=高度= 25。但是对于&#39; |&#39;它给出了fface-&gt; glyph-&gt; bitmap.rows == 26。 对于任何普通字体,我应该如何设置高度以获得25px输出,而不是26?如果不是 可能,那么有没有办法计算输出字符高度以前的像素 FT_Render_Glyph。 FT_Set_Pixel_Sizes不能很好地工作,所以我有时会得+ 1px。

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

3 个答案:

答案 0 :(得分:2)

这已经太晚了,但我刚刚知道如何做到这一点:

  1. (获取字符高度,以像素为单位)。根据我的理解设置字体大小(例如使用FT_Set_Char_Size),实际上只定义了字体单位和像素单位(this explains more)之间的缩放比例。即,12d字体在72dpi并不一定意味着字形是12像素高。但是,您可以获得一个边界框,我非常确定将所选字体中的每个字形都包含在内。我就这样做了:
  2. 
        //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. 这就是我获得基线高度的方法。它只是任何字形基线以下的最大下降。与上面的代码配对时,在此位置绘制带有基线的字形应该保证所有字形都适合边界框。
    2. 
          //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,所以它取消了

答案 1 :(得分:0)

没有人回答任何问题,所以发布了一些比我自己找到的答案更多的解决方法。

对于问题1,我可以在应用以下内容后继续使用:

FT_Set_Pixel_Sizes(fface,w-1,h-1);

或者甚至

FT_Set_Pixel_Sizes(fface,w-w%2,h-h%2);

问题2我还不知道......

答案 2 :(得分:0)

因为我没有看到答案,我会假设使用Freetype我不想做什么,并继续使用OS字体API。