FreeType 如何计算预付款?

How is FreeType calculating advance?

我想弄清楚 FreeType 库是如何计算 FT_GlyphSlotRec_advance 变量的。根据该结构上方的注释块,该变量与进一步解释 herehoriAdvance 变量相同,后者包含在 FT_Glyph_Metrics_ 结构中。

无论如何,以典型的Arial窄字体为例。它可以在 C:\Windows\Fonts\ARIALN.TTF 中找到。将其上传到任何基于 Web 的 TTF 文件编辑器 (option 1, option 2),或使用您自己的可以解释 TTF 文件的程序(fontforge 等),您可以看到 '!' 的 Advance。字符明确定义为 467.

我是运行下面的代码,当我读取FT_GlyphSlotRec_advance.x值时,我得到的值是1472。显然这和467不一样。我我误解了这代表什么?还是我错误地使用了 FreeType 库?

我正在重新输入以前从没有互联网的计算机上获取 1472 的代码,所以请原谅我的任何普通语法错误。

#include <string>
#include <ft2build.h>
#include FT_FREETYPE_H

using namespace std;

int main() {
  FT_Uint font_height = 100;
  FT_Library ft;
  FT_Face face;
  char* filepathname; // Defined through code that was excluded for the sake of simplifying this example

  FT_Init_FreeType(&ft);
  FT_New_Face(ft, filepathname, 0, &face);
  FT_Set_Pixel_Sizes(face, 0, font_height);
  
  FT_Uint glyph_idx = FT_Get_Char_Index(face, 33);
  FT_Load_Glyph(face, glyph_index, FT_LOAD_RENDER);

  FT_Pos advance_x = face->glyph->advance.x;

  return 0;
}

main() 末尾换行导致 advance_x 为 1472。

如您在问题中链接的教程第 2 步页面所示,这些指标通常以 26.6 像素格式报告。您正在通过加载字体的方式修改它。您可以使用 FT_LOAD_NO_SCALE 来“[不] 缩放加载的轮廓字形,但将其保持在字体单位中。”

您的代码在默认屏幕分辨率 72 dpi 下以您请求的大小生成字形的位图版本。您得到的 1472 是用于在位图中绘制字符的像素数 * 64。因此,在这种情况下,1472 / 64 = 23 像素,如果您将多个字符绘制到同一个位图中,这将是您绘制 cursor/pen 点前进的距离。

467 是 1/2048 向量单位。要使用 100 像素的 font_height 进行转换,它是:467/2048 * 100 像素,即 22.8 像素。舍入为 23 像素。乘以 64 得到 1472 个 1/64 像素。

如果你想看到它与像素值对齐,请将你的 font_height 设置为 2048,然后将生成的 face->glyph->advance.x (29888) 除以 64,这会给467.

以下脚本将为您提供所需的值:

#include <string>
#include <ft2build.h>
#include <stdio.h>
#include FT_FREETYPE_H

using namespace std;

int main() {
  FT_Library ft;
  FT_Face face;
  string filepathname = "./arialn.ttf";

  FT_Init_FreeType(&ft);
  FT_New_Face(ft, filepathname.c_str(), 0, &face);
  
  FT_UInt glyph_idx = FT_Get_Char_Index(face, '!');
  FT_Load_Glyph(face, glyph_idx, FT_LOAD_NO_SCALE);

  printf("width=%ld height=%ld\nhoriBearingX=%ld horiBearingY=%ld horiAdvance=%ld\n vertBearingX=%ld vertBearingY=%ld vertAdvance=%ld\n",face->glyph->metrics.width,face->glyph->metrics.height,face->glyph->metrics.horiBearingX,face->glyph->metrics.horiBearingY,face->glyph->metrics.horiAdvance,face->glyph->metrics.vertBearingX,face->glyph->metrics.vertBearingY,face->glyph->metrics.vertAdvance);
  FT_Pos advance_x = face->glyph->advance.x;
  printf("advance_x = %ld \n",advance_x);

  return 0;
}

输出:

width=183 height=1466
horiBearingX=148 horiBearingY=1466 horiAdvance=467
vertBearingX=-85 vertBearingY=228 vertAdvance=1922
advance_x = 467