FreeType rendering text with ortho flipping, difference between vertex and glyph base

I am working on a project in which I implement a FreeType rendering object to draw text for which the visualization environment is specified with an orthographic projection matrix:

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

This ensures that the coordinates are similar to standard GUI systems, with (0,0) being the upper left part of the window instead of the lower left.

However, when rendering using FreeType, everything becomes complicated, because FreeType works with their beginning in the lower left corner of the glyph (minus descender). My problem is similar to https://stackoverflow.com/questions/25353472/render-freetype-gl-text-with-flipped-projection , but the answer has not yet been provided and its solution was not to their liking (the library used is also slightly different, I suppose he uses a wrapper).

So, I am making my text as follows:

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

Of which the 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 do it like this, it will display the text at y coordinate 0 so that it is not visible unless I add an offset to the y coordinate. So, let's look at the FreeType glyph metrics:

glyph metrics from FreeType

I want to shift the y position by a positive amount equal to the difference between the beginning and the top of the glyph image so that it always accurately displays the text at my given position. Looking at the image, I find this to be yMax, so I added the following code to the code before updating VBO:

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

It seemed like a problem when I downloaded FreeType glyphs with a font size of 24, but as soon as I tried to use different font sizes, it couldn't work, as shown in this image:

font size differences

As you can see, this clearly does not work as I thought. I searched through FreeType for documentation if I had something missing, but I could not find it. Am I using the wrong metrics (using Ascender also doesn't work)?

+5
source share
1 answer

I want to shift the y position by a positive amount equal to the difference between the beginning and the top of the glyph image so that it always accurately displays the text at my given position. Looking at the image, I find this to be yMax , so I added the following code to the code before updating VBO:

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

In fact, yMax not what interests you. You can use yMax - yMin to find the height of your glyph, but that's really all that is good for.

From the FreeType 2 API documentation FT_GlyphSlotRec::bitmap_top :

Bitmap bearing expressed in whole pixels. Remember that this is the distance from the baseline to the uppermost glyph line of the scan, and the y coordinates up are positive .

Look at the image you included in your question again, which is effectively bearingY . Your problem is that you subtract this value from your ypos when you shouldn't have it. You need a value, as I explain below, but you definitely don't want to subtract it.

If you excluded bitmap_top from your ypos calculation, you will get the following:

False alignment

This is clearly wrong because it ignores the differences in climbing between each character in your string.

Now carefully consider the following correctly aligned diagram:

5DPfQ.png

In the above diagram, I have illustrated your line with the topmost line, the red, the lowest in green and the baseline for all your glyphs in gray.

As you can see, the main letter 'T' has the greatest ascension, and this generalization holds true for most fonts. Right below the red line, I illustrated the difference in the rise between the capital 'T' and the current letter as the yellow area. This is an important value that you must calculate in order to align the string correctly.

The yellow area in the correctly aligned picture above can be calculated this way:

  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 a correctly aligned diagram.


For bonus points, if you want to align your text from the bottom of the screen, the concept is very similar only to you, you are interested in the difference between the character with the greatest descent (often with the lower case 'g' ) and the current character. This is the distance between the gray base and the green line and can be expressed as height - bearingY in your metric digit.

You should be able to calculate the descent using this:

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

Source: https://habr.com/ru/post/1209004/


All Articles