freetype/harfbuzz: getGlyphInfos() returns incorrect values #415

Closed
opened 2022-07-18 04:06:39 +00:00 by ghost · 6 comments
ghost commented 2022-07-18 04:06:39 +00:00 (Migrated from github.com)

When using harfbuzz with freetype, getGlyphInfos() returns incorrect values compared to using hb_buffer_get_glyph_infos() directly.
Here's code using Arabic text with Amiri-Regular font, but the problem happens in English and other fonts too.
The output of the program is

using getGlyphInfos()
.harfbuzz.buffer.GlyphInfo{ .codepoint = 65, .cluster = 2147484224 }
.harfbuzz.buffer.GlyphInfo{ .codepoint = 10, .cluster = 2 }
.harfbuzz.buffer.GlyphInfo{ .codepoint = 7, .cluster = 1620 }
.harfbuzz.buffer.GlyphInfo{ .codepoint = 2147484179, .cluster = 8 }
.harfbuzz.buffer.GlyphInfo{ .codepoint = 18, .cluster = 16777223 }
.harfbuzz.buffer.GlyphInfo{ .codepoint = 1729, .cluster = 2147484291 }
using c.hb_buffer_get_glyph_infos()
.freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 65, .mask = 2147484224, .cluster = 10, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7fff686f397c, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7fff686f3980 }
.freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 1620, .mask = 2147484179, .cluster = 8, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7fff686f397c, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7fff686f3980 }
.freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 1729, .mask = 2147484291, .cluster = 6, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7fff686f397c, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7fff686f3980 }
.freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 1735, .mask = 2147484291, .cluster = 4, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7fff686f397c, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7fff686f3980 }
.freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 1815, .mask = 2147484192, .cluster = 2, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7fff686f397c, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7fff686f3980 }
.freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 55, .mask = 2147484224, .cluster = 0, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7fff686f397c, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7fff686f3980 }

When using harfbuzz with freetype, getGlyphInfos() returns incorrect values compared to using hb_buffer_get_glyph_infos() directly. Here's [code](https://gist.github.com/AB55AL/520d50dd05c8b72665a2efa6844cd341) using Arabic text with Amiri-Regular font, but the problem happens in English and other fonts too. The output of the program is ``` using getGlyphInfos() .harfbuzz.buffer.GlyphInfo{ .codepoint = 65, .cluster = 2147484224 } .harfbuzz.buffer.GlyphInfo{ .codepoint = 10, .cluster = 2 } .harfbuzz.buffer.GlyphInfo{ .codepoint = 7, .cluster = 1620 } .harfbuzz.buffer.GlyphInfo{ .codepoint = 2147484179, .cluster = 8 } .harfbuzz.buffer.GlyphInfo{ .codepoint = 18, .cluster = 16777223 } .harfbuzz.buffer.GlyphInfo{ .codepoint = 1729, .cluster = 2147484291 } using c.hb_buffer_get_glyph_infos() .freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 65, .mask = 2147484224, .cluster = 10, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7fff686f397c, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7fff686f3980 } .freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 1620, .mask = 2147484179, .cluster = 8, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7fff686f397c, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7fff686f3980 } .freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 1729, .mask = 2147484291, .cluster = 6, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7fff686f397c, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7fff686f3980 } .freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 1735, .mask = 2147484291, .cluster = 4, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7fff686f397c, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7fff686f3980 } .freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 1815, .mask = 2147484192, .cluster = 2, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7fff686f397c, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7fff686f3980 } .freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 55, .mask = 2147484224, .cluster = 0, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7fff686f397c, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7fff686f3980 } ```
alichraghi commented 2022-07-18 05:41:29 +00:00 (Migrated from github.com)

optionally, could you compare output without binding?

optionally, could you compare output without binding?
ghost commented 2022-07-18 06:39:14 +00:00 (Migrated from github.com)

Sure. It looks to be the same.

using bindings of both freetype and harfbuzz
.harfbuzz.buffer.GlyphInfo{ .codepoint = 65, .cluster = 2147484224 }
.harfbuzz.buffer.GlyphInfo{ .codepoint = 10, .cluster = 2 }
.harfbuzz.buffer.GlyphInfo{ .codepoint = 7, .cluster = 1620 }
.harfbuzz.buffer.GlyphInfo{ .codepoint = 2147484179, .cluster = 8 }
.harfbuzz.buffer.GlyphInfo{ .codepoint = 18, .cluster = 16777223 }
.harfbuzz.buffer.GlyphInfo{ .codepoint = 1729, .cluster = 2147484291 }
------------------------------
freetype and harfbuzz without bindings
.freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 65, .mask = 2147484224, .cluster = 10, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c118c, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1190 }
.freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 1620, .mask = 2147484179, .cluster = 8, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c118c, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1190 }
.freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 1729, .mask = 2147484291, .cluster = 6, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c118c, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1190 }
.freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 1735, .mask = 2147484291, .cluster = 4, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c118c, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1190 }
.freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 1815, .mask = 2147484192, .cluster = 2, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c118c, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1190 }
.freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 55, .mask = 2147484224, .cluster = 0, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c118c, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1190 }
------------------------------
freetype with bindings. harfbuzz without bindings
.freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 65, .mask = 2147484224, .cluster = 10, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1144, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1148 }
.freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 1620, .mask = 2147484179, .cluster = 8, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1144, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1148 }
.freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 1729, .mask = 2147484291, .cluster = 6, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1144, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1148 }
.freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 1735, .mask = 2147484291, .cluster = 4, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1144, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1148 }
.freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 1815, .mask = 2147484192, .cluster = 2, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1144, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1148 }
.freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 55, .mask = 2147484224, .cluster = 0, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1144, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1148 }

Sure. It looks to be the same. ``` using bindings of both freetype and harfbuzz .harfbuzz.buffer.GlyphInfo{ .codepoint = 65, .cluster = 2147484224 } .harfbuzz.buffer.GlyphInfo{ .codepoint = 10, .cluster = 2 } .harfbuzz.buffer.GlyphInfo{ .codepoint = 7, .cluster = 1620 } .harfbuzz.buffer.GlyphInfo{ .codepoint = 2147484179, .cluster = 8 } .harfbuzz.buffer.GlyphInfo{ .codepoint = 18, .cluster = 16777223 } .harfbuzz.buffer.GlyphInfo{ .codepoint = 1729, .cluster = 2147484291 } ------------------------------ freetype and harfbuzz without bindings .freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 65, .mask = 2147484224, .cluster = 10, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c118c, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1190 } .freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 1620, .mask = 2147484179, .cluster = 8, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c118c, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1190 } .freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 1729, .mask = 2147484291, .cluster = 6, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c118c, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1190 } .freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 1735, .mask = 2147484291, .cluster = 4, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c118c, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1190 } .freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 1815, .mask = 2147484192, .cluster = 2, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c118c, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1190 } .freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 55, .mask = 2147484224, .cluster = 0, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c118c, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1190 } ------------------------------ freetype with bindings. harfbuzz without bindings .freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 65, .mask = 2147484224, .cluster = 10, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1144, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1148 } .freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 1620, .mask = 2147484179, .cluster = 8, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1144, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1148 } .freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 1729, .mask = 2147484291, .cluster = 6, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1144, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1148 } .freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 1735, .mask = 2147484291, .cluster = 4, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1144, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1148 } .freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 1815, .mask = 2147484192, .cluster = 2, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1144, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1148 } .freetype.c.cimport:1:20.struct_hb_glyph_info_t{ .codepoint = 55, .mask = 2147484224, .cluster = 0, .var1 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1144, .var2 = .freetype.c.cimport:1:20.union__hb_var_int_t@7ffc052c1148 } ```
alichraghi commented 2022-07-18 18:15:15 +00:00 (Migrated from github.com)

i believe #418 can fix this. but as a workaround you can test it yourself because i don't have a codebase for testing (this is an issue)

i believe #418 can fix this. but as a workaround you can test it yourself because i don't have a codebase for testing (this is an issue)
ghost commented 2022-07-19 04:37:40 +00:00 (Migrated from github.com)

Hey Ali. Unfortunately the issue hasn't been fixed. The length wasn't the problem. I looked into it today and it seems the values of the codepoint, mask, and cluster are getting mixed together. I was able to solve it by changing the GlyphInfo struct members to

    codepoint: u32,
    mask: u32,
    cluster: u32,
    var1: u32,
    var2: u32,

Adding mask, var1 and var2 makes the size of GlyphInfo the same as hb_glyph_info_t. and results in correct values.

Hey Ali. Unfortunately the issue hasn't been fixed. The length wasn't the problem. I looked into it today and it seems the values of the *codepoint*, *mask*, and *cluster* are getting mixed together. I was able to solve it by changing the *GlyphInfo* struct members to ```zig codepoint: u32, mask: u32, cluster: u32, var1: u32, var2: u32, ``` Adding *mask*, *var1* and *var2* makes the size of *GlyphInfo* the same as *hb_glyph_info_t*. and results in correct values.
alichraghi commented 2022-07-19 05:06:46 +00:00 (Migrated from github.com)

thanks for the solution

thanks for the solution
ghost commented 2022-07-19 05:18:26 +00:00 (Migrated from github.com)

Happy to help. And thanks for the bindings, they've been very helpful.

Happy to help. And thanks for the bindings, they've been very helpful.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
hexops/mach#415
No description provided.