使用翻转正交渲染 FreeType 文本,字形顶部和基线之间的差异 [英] Render FreeType text with flipped ortho, difference between top and baseline of glyph

查看:111
本文介绍了使用翻转正交渲染 FreeType 文本,字形顶部和基线之间的差异的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个项目,在该项目中我实现了一个 FreeType 渲染对象来绘制使用正交投影矩阵指定渲染环境的文本:

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

这确保坐标类似于标准 GUI 系统,(0,0) 是窗口的左上角而不是左下角.

然而,当使用 FreeType 进行渲染时,事情会变得困难,因为 FreeType 的原点位于字形的左下角(减去下行部分).我的问题类似于 是:<块引用>

位图的顶部方位以整数像素表示.请记住,这是从基线到最顶部字形扫描线的距离,向上的 y 坐标为.

再次查看您在问题中包含的图片,它实际上是 bearingY.您的问题是您不应该从 ypos 中减去这个值.正如我将在下面解释的那样,您确实需要该值,但您绝对不想减去它.

如果您从 ypos 的计算中消除 bitmap_top,您将得到以下结果:

这显然是不正确的,因为它忽略了字符串中每个字符之间的上升差异.

现在,仔细看看下面正确对齐的图表:

在上图中,我用红色表示字符串最上面的线,用绿色表示最下面的线,用灰色表示所有字形的基线.

如您所见,大写字母 'T' 的上升幅度最大,这种概括适用于大多数字体.在红线正下方,我用黄色区域说明了大写 'T' 和当前字母之间的上升差异.这是您必须计算以正确对齐字符串的重要数量.

上图中正确对齐的黄色区域可以这样计算:

 Chars['T'].bitmap_top - 字形->bitmap_top

如果您停止从 ypos 中减去 glyph->bitmap_top 并添加上面的值,您应该得到与正确对齐的图表相同的结果.

<小时>

对于加分,如果您想将文本与屏幕的底部对齐,概念非常相似,只是您对字符之间的差异感兴趣具有最大的下降(通常是小写的 'g')和当前字符.这是灰色基线和绿色线之间的距离,可以在字形指标图中表示为 height -bearingY.

你应该能够使用这个计算下降:

(glyph->metrics.height >>6) - glyph->bitmap_top//bitmap_top 是整数坐标

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:

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.

However when rendering using FreeType, things get difficult, because FreeType operates with their origin at the bottom-left of a glyph (minus the descender). 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).

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(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. So looking at FreeType's glyph metrics:

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. 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:

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:

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. Am I using the wrong metrics (using Ascender didn't work as well)?

解决方案

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. 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:

    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.

From the FreeType 2 API documentation, FT_GlyphSlotRec::bitmap_top is:

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.

Look at the image you included in your question again, that is effectively bearingY. Your problem is that you are subtracting this value from your ypos when you should not be. 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:

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. Directly below the red line, I have illustrated the difference in ascent between capital 'T' and the current letter as the yellow area. 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.


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. That is the distance between the grey baseline and the green line and can be expressed as height - bearingY in your glyph metrics figure.

You should be able to compute descent using this:

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

这篇关于使用翻转正交渲染 FreeType 文本,字形顶部和基线之间的差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆