From f75f3d40e434a3f5faee36b88307ab62e6090cc1 Mon Sep 17 00:00:00 2001 From: Yiheng Wu <36156959+jingkaimori@users.noreply.github.com> Date: Wed, 18 Jun 2025 21:37:50 +0800 Subject: [PATCH] Calculate font unit per pixel dynamically (#1629) This PR turns font unit per pixel (a "magic number") into actually computed value. Previously the "font unit per pixel" is hardcoded as float `4.0`, because `units_per_EM` field of unscii is 64, and default font size is 16. If another font is loaded, layout will be corrupted by invalid scaling of `glyphPositions`. Note that only transformation from font unit to pixel is affected, no visual change is made, and width of glyph(character) is not changed. --- src/graphics.zig | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/graphics.zig b/src/graphics.zig index 37fa046a..88663fad 100644 --- a/src/graphics.zig +++ b/src/graphics.zig @@ -843,10 +843,10 @@ pub const TextBuffer = struct { // MARK: TextBuffer // Merge it all together: self.glyphs = allocator.alloc(GlyphData, glyphInfos.len); for(self.glyphs, 0..) |*glyph, i| { - glyph.x_advance = @as(f32, @floatFromInt(glyphPositions[i].x_advance))/4.0; - glyph.y_advance = @as(f32, @floatFromInt(glyphPositions[i].y_advance))/4.0; - glyph.x_offset = @as(f32, @floatFromInt(glyphPositions[i].x_offset))/4.0; - glyph.y_offset = @as(f32, @floatFromInt(glyphPositions[i].y_offset))/4.0; + glyph.x_advance = @as(f32, @floatFromInt(glyphPositions[i].x_advance))/TextRendering.fontUnitsPerPixel; + glyph.y_advance = @as(f32, @floatFromInt(glyphPositions[i].y_advance))/TextRendering.fontUnitsPerPixel; + glyph.x_offset = @as(f32, @floatFromInt(glyphPositions[i].x_offset))/TextRendering.fontUnitsPerPixel; + glyph.y_offset = @as(f32, @floatFromInt(glyphPositions[i].y_offset))/TextRendering.fontUnitsPerPixel; glyph.character = @intCast(parser.parsedText.items[textIndexGuess[i]]); glyph.index = glyphInfos[i].codepoint; glyph.cluster = glyphInfos[i].cluster; @@ -1149,6 +1149,7 @@ const TextRendering = struct { // MARK: TextRendering var textureWidth: i32 = 1024; const textureHeight: i32 = 16; var textureOffset: i32 = 0; + var fontUnitsPerPixel: f32 = undefined; fn ftError(errorCode: hbft.FT_Error) !void { if(errorCode == 0) return; @@ -1176,6 +1177,7 @@ const TextRendering = struct { // MARK: TextRendering try ftError(hbft.FT_Set_Pixel_Sizes(freetypeFace, 0, textureHeight)); harfbuzzFace = hbft.hb_ft_face_create_referenced(freetypeFace); harfbuzzFont = hbft.hb_font_create(harfbuzzFace); + fontUnitsPerPixel = @as(f32, @floatFromInt(freetypeFace.*.units_per_EM))/@as(f32, @floatFromInt(textureHeight)); glyphMapping = .init(main.globalAllocator); glyphData = .init(main.globalAllocator);