freetype
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

FT_GlyphSlot: load hinted + lsb_delta - rsb_delta xadvance differs with


From: takase1121
Subject: FT_GlyphSlot: load hinted + lsb_delta - rsb_delta xadvance differs with unhinted
Date: Sun, 07 Jul 2024 14:22:00 +0000

Hi,

According to the documentation on lsb and rsb_delta:

https://freetype.org/freetype2/docs/reference/ft2-glyph_retrieval.html#ft_glyphslotrec

The fields are described as the "difference between hinted and unhinted 
left/right-side bearing", and the code underneath describes how to calculate 
the 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 and 
unhinted xadvances are different. I tested this program with JetBrains Mono 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 (Punctuation 
Space). I guess that the lsb_delta and rsb_delta are not set because there is 
nothing to hint (they're all whitespaces). I would like to confirm 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) {
    FT_Library lib;
    FT_Face face;

    if (argc != 2) return 1;

    if (FT_Init_FreeType(&lib) != 0)
        return 1;

    if (FT_New_Face(lib, argv[1], 0, &face) != 0)
        return 1;

    if (FT_Set_Pixel_Sizes(face, 0, 14) != 0)
        return 1;

    printf("Family: %s\n", face->family_name);

for (int i = 0; i < 0x10FFFF; i++) {
        if (FT_Load_Char(face, i, FT_LOAD_TARGET_LIGHT | 
FT_LOAD_FORCE_AUTOHINT) != 0)
            return 1;

        double hinted_xadv = (face->glyph->advance.x + (face->glyph->lsb_delta 
- face->glyph->rsb_delta)) / 64.0f;

double bearing_delta = (face->glyph->lsb_delta - face->glyph->rsb_delta) / 
64.0f;


        if (FT_Load_Char(face, i, FT_LOAD_BITMAP_METRICS_ONLY | 
FT_LOAD_NO_HINTING) != 0)
            return 1;

        double unhinted_xadv = (face->glyph->advance.x) / 64.0f;


        if (hinted_xadv != unhinted_xadv) {
            printf("different advances (U+%04X): %lf hinted, %lf unhinted\n", 
i, hinted_xadv, unhinted_xadv);
            printf("lsb_delta - rsb_delta: %f\n", bearing_delta);
        }
    }
    printf("\n\n");

    return 0;
}

---


Sample results:

---

Family: Fira Sansdifferent advances (U+000D): 4.000000 hinted, 3.703125 unhinted
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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]