简体   繁体   English

使用翻转的正交渲染FreeType文本,字形的顶部和基线之间的差异

[英]Render FreeType text with flipped ortho, difference between top and baseline of glyph

I am working on a project where I implement a FreeType rendering object to draw text of which the rendering environment is specified with an orthographic projection matrix: 我正在开发一个项目,我在其中实现一个FreeType渲染对象来绘制文本,其中渲染环境是使用正交投影矩阵指定的:

glm::ortho(0, Width, Height, 0);

This makes sure the coordinates are similar to standard GUI systems with (0,0) being the top-left part of the window instead of the bottom-left. 这确保坐标类似于标准GUI系统,其中(0,0)是窗口的左上部分而不是左下角。

However when rendering using FreeType, things get difficult, because FreeType operates with their origin at the bottom-left of a glyph (minus the descender). 然而,当使用FreeType进行渲染时,事情变得困难,因为FreeType的操作原点位于字形的左下角(减去下降部分)。 My issue is similar to https://stackoverflow.com/questions/25353472/render-freetype-gl-text-with-flipped-projection but no answer was yet provided and his solution was not to my liking (the used library is also slightly different, I assume he is using a wrapper). 我的问题类似于https://stackoverflow.com/questions/25353472/render-freetype-gl-text-with-flipped-projection但尚未提供答案,他的解决方案不符合我的意愿(使用的库也是略有不同,我假设他正在使用包装器)。

So I render my text as follows: 所以我将我的文字渲染如下:

renderText("Testing 123 if text performs sufficiently", 0.0f, 0.0f, 1.0f, 1.0f);

Of which renderText function contains: 其中renderText函数包含:

renderText(const GLchar *text, GLfloat x, GLfloat y, GLfloat sx, GLfloat sy)
{
    [...]
    GLfloat xpos = x + glyph->bitmap_left * sx; 
    GLfloat ypos = y - glyph->bitmap_top * sy; 
    GLfloat w = glyph->bitmap.width * sx;
    GLfloat h = glyph->bitmap.rows * sy;
    // Update VBO
    GLfloat vertices[4][4] = {
        { xpos,     ypos,       0, 0 },
        { xpos + w, ypos,       1, 0 },
        { xpos,     ypos + h,   0, 1 },
        { xpos + w, ypos + h,   1, 1 }
    };
    [...]
}

If I render it like this, it will render the text below the y coordinate of 0 so it won't be visible unless I add an offset to the y coordinate. 如果我像这样渲染它,它将渲染y坐标为0以下的文本,因此除非我向y坐标添加偏移量,否则它将不可见。 So looking at FreeType's glyph metrics: 所以看一下FreeType的字形指标:

FreeType中的字形指标

I want to offset the y position by a positive amount equal to the difference between the origin and the top of the glyph image so it always neatly renders the text at my given position. 我想将y位置偏移一个等于字形图像的原点和顶部之间的差值的正数量,这样它总能整齐地将文本呈现在我给定的位置。 Looking at the image I believe this to be the yMax value so I added the following statement to the code before updating the VBO: 查看图像我认为这是yMax值,所以我在更新VBO之前将以下语句添加到代码中:

ypos += (glyph->face->bbox.yMax >> 6) * sy; 

Which seemed to fix the issue when I loaded the FreeType glyphs with font size 24, but as soon as I tried to use different font sizes it failed to work as this image shows: 当我加载字体大小为24的FreeType字形时,似乎解决了这个问题,但是当我尝试使用不同的字体大小时,它无法正常工作,因为此图像显示:

字体大小差异

As you can see, it clearly doesn't work as I thought it would. 正如你所看到的,它显然不能像我想象的那样工作。 I've been thouroughly searching through FreeType's documentation if I was missing something, but I could not find it. 如果我遗漏了一些东西,我一直在搜索FreeType的文档,但我找不到它。 Am I using the wrong metrics (using Ascender didn't work as well)? 我使用错误的指标(使用Ascender不起作用)?

I want to offset the y position by a positive amount equal to the difference between the origin and the top of the glyph image so it always neatly renders the text at my given position. 我想将y位置偏移一个等于字形图像的原点和顶部之间的差值的正数量,这样它总能整齐地将文本呈现在我给定的位置。 Looking at the image I believe this to be the yMax value so I added the following statement to the code before updating the VBO: 查看图像我认为这是yMax值,所以我在更新VBO之前将以下语句添加到代码中:

    ypos += (glyph->face->bbox.yMax >> 6) * sy;

In actuality, yMax is not what you are interested in. You could use yMax - yMin to find the height of your glyph, but that is really all it is good for. 实际上, yMax并不是你感兴趣的。你可以使用yMax - yMin来找到你的字形的高度,但这确实是它的好处。

From the FreeType 2 API documentation, FT_GlyphSlotRec::bitmap_top is: 从FreeType 2 API文档中, FT_GlyphSlotRec::bitmap_top是:

The bitmap's top bearing expressed in integer pixels. 位图的顶部方位以整数像素表示。 Remember that this is the distance from the baseline to the top-most glyph scanline, upwards y coordinates being positive . 请记住,这是从基线到最顶部字形扫描线的距离,向上y坐标为

Look at the image you included in your question again, that is effectively bearingY . 再看看你在问题中包含的图像,即有效bearingY Your problem is that you are subtracting this value from your ypos when you should not be. 你的问题是你不应该从你的ypos中减去这个值。 You do need the value as I will explain below, but you definitely do not want to subtract it. 你确实需要这个值,我将在下面解释,但你绝对不想减去它。

If you eliminate bitmap_top from your calculation of ypos you get the following: 如果从ypos的计算中删除bitmap_top ,则会得到以下内容:

错误对齐

Which is obviously incorrect because it ignores differences in ascent between each character in your string. 这显然是不正确的,因为它忽略了字符串中每个字符之间的上升差异。

Now, take a close look at the following correctly aligned diagram: 现在,仔细查看以下正确对齐的图表:

In the diagram above, I have illustrated your string's top-most line in red, bottom-most in green and the baseline for all of your glyphs in grey. 在上图中,我已经说明了你的字符串最顶部的红线,最底部的绿色和灰色的所有字形的基线。

As you can see, the capital letter 'T' has the greatest ascent and this generalization holds true for most fonts. 正如您所看到的,大写字母'T'具有最大的上升,并且这种泛化适用于大多数字体。 Directly below the red line, I have illustrated the difference in ascent between capital 'T' and the current letter as the yellow area. 在红线正下方,我已经说明了资本'T'和当前字母之间的上升差异为黄色区域。 This is the important quantity that you must calculate to properly align your string. 这是您必须计算以正确对齐字符串的重要数量。

The yellow region in the correctly aligned figure above can be calculated thus: 可以如下计算上面正确对齐的图中的黄色区域:

    Chars['T'].bitmap_top - glyph->bitmap_top

If you stop subtracting glyph->bitmap_top from ypos and add the value above, you should get the same results as the correctly aligned diagram. 如果你停止从ypos减去glyph->bitmap_top并添加上面的值,你应该得到与正确对齐的图相同的结果。


For bonus points, if you want to align your text to the bottom of the screen, the concept is very similar only you are interested in the difference between the character with the greatest descent (often lowercase 'g' ) and the current character. 对于奖励积分,如果您想将文本与屏幕底部对齐,则概念非常相似,只有您对最大下降的角色(通​​常是小写的'g' )与当前角色之间的差异感兴趣。 That is the distance between the grey baseline and the green line and can be expressed as height - bearingY in your glyph metrics figure. 这是灰色基线和绿线之间的距离,可以在您的字形度量图中表示为height - bearingY

You should be able to compute descent using this: 您应该能够使用以下方法计算下降:

(glyph->metrics.height >> 6) - glyph->bitmap_top // bitmap_top is in integer coords

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM