nothings / stb

stb single-file public domain libraries for C/C++
https://twitter.com/nothings
Other
26.55k stars 7.69k forks source link

stb_truetype: stbtt_GetCodepointHMetrics() outputs weird advanceWidth values after being called several times #1601

Open Alihene opened 8 months ago

Alihene commented 8 months ago

Describe the bug When calling stbtt_GetCodepointHMetrics() on every character of a string, after a certain point the advanceWidth ends up being set to weird values. When using Arial, the advance width gets set to 13235 at a certain character and then 0 for the remaining characters. The point at which the values get weird varies for every string, The values are sometimes negative as well, for example -32548. however it mostly occurs in strings that are 30+ characters long. As a side note, no kerning is present.

To Reproduce

  1. Init "Arial" font
  2. Loop through every character in the string abcdefghijklmnopqrstuvwxyz1234567890 and call stbtt_GetCodepointHMetrics() on every character (the advanceWidth should become 13235 for the character 8)

Expected behavior The advanceWidth should be the correct advance width for the character.

Screenshots Screenshot_20240128_152223

scippie75 commented 6 months ago

You should share your code. Sounds like you maybe freed/released the ttf data itself and only kept the font_info struct? The ttf font data should also be kept in memory for as long as you use the font.

It's hard to detect that problem because right after doing it, the memory may no longer be 'allocated' according to the system but the data is still in there and is in a page you have been granted access to. When you start allocating new things, that space gets overwritten and starts invalidating the font data that is still being used.

jakitliang commented 1 month ago

You should share your code. Sounds like you maybe freed/released the ttf data itself and only kept the font_info struct? The ttf font data should also be kept in memory for as long as you use the font.

It's hard to detect that problem because right after doing it, the memory may no longer be 'allocated' according to the system but the data is still in there and is in a page you have been granted access to. When you start allocating new things, that space gets overwritten and starts invalidating the font data that is still being used.

int advanceX, leftSideBearing;
stbtt_GetCodepointHMetrics(&FontInfo, (int) codePoint, &advanceX, &leftSideBearing); // Get 128

But font size I need is 28pt

scippie75 commented 1 month ago

With 'share your code' I meant all the code relating to the font, which means all calls to stbtt and all memory related code on the data that gets passed to stbtt. The code you shared could already fail when passed an uninitialized FontInfo struct to it.

Like I said in the previous post, I am quite certain that your FontInfo is all right, but that the font data (the actual file data) you passed to the function where you created that FontInfo, is no longer available, probably because you put it in a memory buffer that you freed already, or put it in an std::vector or similar and it got out of scope. The font data needs to stay in memory all the time use use FontInfo.