A little problem with ttf font

Original link: https://blog.codingnow.com/2023/07/ttf_fontsize.html

Our game engine uses stb’s truetype library to handle ttf fonts. Recently, I found that there was a problem when using the Alibaba Puhui provided by the company.

The Chinese characters rendered by the engine are much shorter than the nominal pixel height. If you want to render a Chinese character with a height of 100 pixels, the result is only about 70+ pixels. The Chinese fonts we used in previous tests (Windows comes with default fonts) do not have this problem.

I flipped through the Internet and found such a post: https://github.com/nothings/stb/issues/689 and imgui also encountered similar problems .

It turns out that the stb truetype library provides two apis for calculating the font size, stbtt_ScaleForPixelHeight() and stbtt_ScaleForMappingEmToPixels() use two methods to calculate the font height ratio. The author advocates using the former api, but also retains the usage scenarios of the latter api.

computes a scale factor to produce a font whose EM size is mapped to ‘pixels’ tall. This is probably what traditional APIs compute, but I’m not positive.

In addition, when obtaining the ascent and decent of the font, there are also two different apis: stbtt_GetFontVMetrics() and stbtt_GetFontVMetricsOS2() .

I looked through the implementation of these APIs curiously, and consulted the documents about truetype that I could find, and came to the following conclusions:

In the font file, there are two places where the ascent and descent values ​​of the font are described. This value should be the pixel size used by the font designer when authoring it. Originally they should be recorded in the hhea table of the font file header, which was originally designed by apple. We can find documents on Apple’s website .

Later, when Microsoft designed the font, it may have found that this information was not enough, or it may not approve of some of Apple’s design decisions. They designed a new table called OS/2, which also has similar fields. Documentation can be found on the Microsoft website .

Why are there many duplicate fields in the two tables, and two copies are placed in the font file (bringing redundant information)? I guess it has something to do with Microsoft’s code implementation style: Microsoft’s very system directly maps the memory structure to the file structure. So they chose to add an entire table instead of just adding the necessary fields in a new table.

For most fonts, the ascent and descent values ​​of the two tables are the same. But as noted in the apple documentation, there is no requirement that they be consistent. A note in the Microsoft documentation mentions:

Some legacy platforms or applications may not use OS/2 fields at all. Thus, CJK fonts generally should have the same descender value recorded in hhea.descender, OS/2.sTypoDescender, and HorizAxis.ideo (if present) fields, and the same ascender value recorded in hhea.ascender, OS/2.sTypoAscender, and HorizAxis.idtp (if present) fields.

Obviously, Alibaba Pratt did not abide by this.

It is in hhea table, ascent = 1050 descent = -322, in os/2, ascent = 850 descent = -150.

When calculating scaling with stbtt_ScaleForPixelHeight() , using pixel / (hhea.ascent – ​​hhea.descent) yields smaller values ​​than expected.

Why stbtt_ScaleForMappingEmToPixels() can get the expected value? Since it is calculated using the unitsPerEm field in the head table, this value is usually equal to ascent – ​​descent (this is also mentioned in the above documentation). In the Alibaba Puhui Ti file, it is also equal to os2.sTypoAscender – os2.sTypoAscender.

I don’t know why this font is filled with such different data. I guess it may have something to do with the default screen dpi adopted by the apple / ms system? It indirectly caused the font designer to misfill some kind of parameter when packaging the font? But anyway, I think it’s a bug in the font itself. Although, I got around this problem by modifying the code of our engine.

In order to verify the conjecture of the font bug, I installed the font to the windows system. It is found that in Notepad, this font behaves similar to that in our engine, and is smaller than the expected size; while in the browser using the wenkit kernel, although the size meets the expectation, the font using this font is selected with the mouse When texting, the size of the background select box is weird, much larger than expected. Other Chinese fonts do not have this problem.

This article is transferred from: https://blog.codingnow.com/2023/07/ttf_fontsize.html
This site is only for collection, and the copyright belongs to the original author.