gpt4 book ai didi

c++ - 如何将字形与Freetype沿基线对齐?

转载 作者:行者123 更新时间:2023-12-02 10:14:37 53 4
gpt4 key购买 nike

我编写了一个使用Freetype2从字体创建图像的函数。我的目标是用字体中的所有字符创建一个OpenGL纹理。但是首先,我要确保正确创建纹理,因此现在将其存储为带有stb_image_write的图像。到目前为止,这是我的进步:

The first few letters from the image

如您所见,字形不是沿着基线对齐的,而是沿着图像的顶部对齐的。因此,我决定引入一个名为“yOffset”的变量,该变量描述每个字形必须向下移动才能正确对齐的像素数量。

根据Render FreeType text with flipped ortho, difference between top and baseline of glyph中的答案,可以使用

yOffset = (Glyph with highest y-Bearing)->bitmap_top - glyph->bitmap_top

该值在第一个循环中存储在“maxAscent”中,该循环找出每个字形的度量。

这是字形指标的直观表示:

enter image description here

这是我的功能:
static void loadFontImage(const std::string& fontPath, unsigned int fontSize, const std::string& imagePath) {
FT_Library library;
FT_Face face;

unsigned int imageWidth = 0;
unsigned int imageHeight = 0;
unsigned int maxAscent = 0;

if (FT_Init_FreeType(&library)) {
std::cerr << "Could not initialize font library" << std::endl;
std::exit(-1);
}

if (FT_New_Face(library, fontPath.c_str(), 0, &face)) {
std::cerr << "Could not load font '" << fontPath << "'" << std::endl;
std::exit(-1);
}

FT_Set_Char_Size(face, 0, fontSize * 64, 300, 300);

FT_GlyphSlot glyph = face->glyph;

for (unsigned int c = 32; c < 256; c++) {
if (c == 127) continue;
if (FT_Load_Char(face, c, FT_LOAD_RENDER)) continue;

imageWidth += glyph->bitmap.width;

if (glyph->bitmap.rows > (int)imageHeight) {
imageHeight = glyph->bitmap.rows;
}

if (glyph->bitmap_top > (int)maxAscent) {
maxAscent = glyph->bitmap_top;
}
}

unsigned int size = imageWidth * imageHeight;
unsigned char* buffer = new unsigned char[size];
unsigned int xOffset = 0;
unsigned int yOffset = 0;

for (unsigned int c = 32; c < 256; c++) {
if (c == 127) continue;
if (FT_Load_Char(face, c, FT_LOAD_RENDER)) continue;

yOffset = maxAscent - glyph->bitmap_top;

for (unsigned int x = 0; x < glyph->bitmap.width; x++) {
for (unsigned int y = 0; y < glyph->bitmap.rows; y++) {
unsigned int imageIndex = (x + xOffset) + (y + yOffset) * imageWidth;
unsigned int bitmapIndex = x + y * glyph->bitmap.width;
buffer[imageIndex] = glyph->bitmap.buffer[bitmapIndex];
}
}

xOffset += glyph->bitmap.width;
}

stbi_write_png(imagePath.c_str(), imageWidth, imageHeight, 1, buffer, imageWidth);

delete[] buffer;
}
}

但是自从我介绍了yOffset以来,“索引超出范围”类型的异常仅在某些字形上发生,因为字形的高度加上yOffset大于图像的高度。

我认为这是因为我的“maxAscent”公式不正确,因此对于某些字符,我的yOffset太大。因此,我的问题是:这确实是正确的公式吗?如果是,那么我的算法还有什么问题吗?也许有一种更简单的方法来实现正确的对齐?

最佳答案

在发现图像的实际高度没有正确计算之后,我用一个简单的解决方法解决了这个问题。这是因为“最高”字形的高度不代表图像的实际高度。例如,一个字符可能小于最高的字形,但放置在基线上方,因此超出范围。

我引入了另一个名为“maxDescent”的变量,该变量存储基线以下的最大像素数。在第一个循环中,其计算如下:

if ((glyph->metrics.height >> 6) - glyph->bitmap_top > (int)maxDescent) {
maxDescent = (glyph->metrics.height >> 6) - glyph->bitmap_top;
}

与“maxAscent”一起使用,该“maxAscent”存储了基线以上的最大像素数量,我可以通过简单地将它们加在一起来计算图像所需的实际高度。
imageHeight = maxAscent + maxDescent

这是结果的一部分:

Resulting Font Image

关于c++ - 如何将字形与Freetype沿基线对齐?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62374506/

53 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com