FT_GlyphSlot: load hinted + lsb_delta - rsb_delta xadvance differs with unhinted
takase1121 <[email protected]> Sun, 07 Jul 2024 14:22:00 +0000
| Newsgroups | gmane.comp.fonts.freetype.user |
|---|---|
| Message-ID | <43UMCwjFZ826gAYM67Ks8ZFNB3R3ZqhxN0kW0O7mOc7MLSU41Snt3UGiCJFakKG8SAkj62nNoljtsleWLWYbMEzxEPaJl9jKmL2szicDFkM=@proton.me> |
Hi,
According to the=C2=A0documentation on lsb and rsb_delta:
https://freetype.org/freetype2/docs/reference/ft2-glyph_retrieval.html#ft_g=
lyphslotrec
The fields are described as the "difference between hinted and unhinted lef=
t/right-side bearing", and the code underneath describes how to calculate t=
he xadvance based on the values. However, the xadvance I got from using FT_=
Load_Glyph with FT_LOAD_TARGET_LIGHT & lsb/rsb_delta is sometimes different=
than FT_Load_Glyph with FT_LOAD_NO_HINTING, especially with whitespace.
I tested this with a simple C program that prints a message if the hinted a=
nd unhinted xadvances are different. I tested this program with JetBrains M=
ono and Fira Sans, and both fonts have differing xadvances on U+000D (CR), =
U+0020 (Space), U+00A0 (No-Break Space), U+2007 (Figure Space), U+2008 (Pun=
ctuation Space). I guess that the lsb_delta and rsb_delta are not set becau=
se there is nothing to hint (they're all whitespaces). I would like to conf=
irm if this is a bug with FreeType or is to be expected. Any help would be =
greatly appreciated.
The C program:
---
// compile with: gcc -o test -I/usr/include/freetype2 test.c -lfreetype
#include <ft2build.h>
#include FT_FREETYPE_H
int main(int argc, const char **argv) {
=C2=A0 =C2=A0 FT_Library lib;
=C2=A0 =C2=A0 FT_Face face;
=C2=A0 =C2=A0 if (argc !=3D 2) return 1;
=C2=A0 =C2=A0 if (FT_Init_FreeType(&lib) !=3D 0)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 return 1;
=C2=A0 =C2=A0 if (FT_New_Face(lib, argv[1], 0, &face) !=3D 0)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 return 1;
=C2=A0 =C2=A0 if (FT_Set_Pixel_Sizes(face, 0, 14) !=3D 0)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 return 1;
=C2=A0 =C2=A0 printf("Family: %s\n", face->family_name);
for (int i =3D 0; i < 0x10FFFF; i++) {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (FT_Load_Char(face, i, FT_LOAD_TARGET_LIGHT =
| FT_LOAD_FORCE_AUTOHINT) !=3D 0)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return 1;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 double hinted_xadv =3D (face->glyph->advance.x =
+ (face->glyph->lsb_delta - face->glyph->rsb_delta)) / 64.0f;
double bearing_delta =3D (face->glyph->lsb_delta - face->glyph->rsb_delta) =
/ 64.0f;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (FT_Load_Char(face, i, FT_LOAD_BITMAP_METRIC=
S_ONLY | FT_LOAD_NO_HINTING) !=3D 0)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return 1;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 double unhinted_xadv =3D (face->glyph->advance.=
x) / 64.0f;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (hinted_xadv !=3D unhinted_xadv) {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 printf("different advances (U+%04=
X): %lf hinted, %lf unhinted\n", i, hinted_xadv, unhinted_xadv);
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 printf("lsb_delta - rsb_delta: %f=
\n", bearing_delta);
=C2=A0 =C2=A0 =C2=A0 =C2=A0 }
=C2=A0 =C2=A0 }
=C2=A0 =C2=A0 printf("\n\n");
=C2=A0 =C2=A0 return 0;
}
---
Sample results:
---
Family: Fira Sansdifferent advances (U+000D): 4.000000 hinted, 3.703125 unh=
inted
lsb_delta - rsb_delta: 0.000000
different advances (U+0020): 4.000000 hinted, 3.703125 unhinted
lsb_delta - rsb_delta: 0.000000
different advances (U+00A0): 4.000000 hinted, 3.703125 unhinted
lsb_delta - rsb_delta: 0.000000
different advances (U+2007): 8.000000 hinted, 7.843750 unhinted
lsb_delta - rsb_delta: 0.000000
different advances (U+2008): 4.000000 hinted, 3.703125 unhinted
lsb_delta - rsb_delta: 0.000000
---
JetBrains Mono: https://www.jetbrains.com/lp/mono/
Fira Sans: https://fonts.google.com/specimen/Fira+Sans
Thanks,
Kelvin