From bfde326bcb2defdf90e98fb60caf083db80b2a97 Mon Sep 17 00:00:00 2001 From: sin-ack Date: Sun, 29 Dec 2024 02:05:37 +0000 Subject: [PATCH] font/freetype: Rewrite monoToGrayscale algorithm The original version had issues converting properly and caused broken glyphs. This version tries to be as simple as possible in order to make it easy to understand. I haven't measured the performance but in practice this will only happen during the first render of the glyph after a face change (i.e. during launch or when changing font size). --- src/font/face/freetype_convert.zig | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/font/face/freetype_convert.zig b/src/font/face/freetype_convert.zig index 298aad8a0..6df350bfa 100644 --- a/src/font/face/freetype_convert.zig +++ b/src/font/face/freetype_convert.zig @@ -43,26 +43,14 @@ pub fn monoToGrayscale(alloc: Allocator, bm: Bitmap) Allocator.Error!Bitmap { var buf = try alloc.alloc(u8, bm.width * bm.rows); errdefer alloc.free(buf); - // width divided by 8 because each byte has 8 pixels. This is therefore - // the number of bytes in each row. - const bytes_per_row = bm.width >> 3; - - var source_i: usize = 0; - var target_i: usize = 0; - var i: usize = bm.rows; - while (i > 0) : (i -= 1) { - var j: usize = bytes_per_row; - while (j > 0) : (j -= 1) { - var bit: u4 = 8; - while (bit > 0) : (bit -= 1) { - const mask = @as(u8, 1) << @as(u3, @intCast(bit - 1)); - const bitval: u8 = if (bm.buffer[source_i + (j - 1)] & mask > 0) 0xFF else 0; - buf[target_i] = bitval; - target_i += 1; - } + for (0..bm.rows) |y| { + const row_offset = y * @as(usize, @intCast(bm.pitch)); + for (0..bm.width) |x| { + const byte_offset = row_offset + @divTrunc(x, 8); + const mask = @as(u8, 1) << @intCast(7 - (x % 8)); + const bit: u8 = @intFromBool((bm.buffer[byte_offset] & mask) != 0); + buf[y * bm.width + x] = bit * 255; } - - source_i += @intCast(bm.pitch); } var copy = bm;