diff --git a/src/font/Atlas.zig b/src/font/Atlas.zig index 3e3a20ad2..969318943 100644 --- a/src/font/Atlas.zig +++ b/src/font/Atlas.zig @@ -306,7 +306,12 @@ pub fn clear(self: *Atlas) void { } /// Dump the atlas as a PPM to a writer, for debug purposes. -/// Only supports grayscale and rgb atlases. +/// Only supports grayscale and bgr atlases. +/// +/// NOTE: BGR atlases will have the red and blue channels +/// swapped because PPM expects RGB. This would be +/// easy enough to fix so next time someone needs +/// to debug a color atlas they should fix it. pub fn dump(self: Atlas, writer: anytype) !void { try writer.print( \\P{c} @@ -316,7 +321,7 @@ pub fn dump(self: Atlas, writer: anytype) !void { , .{ @as(u8, switch (self.format) { .grayscale => '5', - .rgb => '6', + .bgr => '6', else => { log.err("Unsupported format for dump: {}", .{self.format}); @panic("Cannot dump this atlas format."); @@ -421,8 +426,16 @@ pub const Wasm = struct { // We need to draw pixels so this is format dependent. const buf: []u8 = switch (self.format) { - // RGBA is the native ImageData format - .rgba => self.data, + .bgra => buf: { + // Convert from BGRA to RGBA by swapping every R and B. + var buf: []u8 = try alloc.dupe(u8, self.data); + errdefer alloc.free(buf); + var i: usize = 0; + while (i < self.data.len) : (i += 4) { + std.mem.swap(u8, &buf[i], &buf[i + 2]); + } + break :buf buf; + }, .grayscale => buf: { // Convert from A8 to RGBA so every 4th byte is set to a value. @@ -575,12 +588,12 @@ test "grow" { try testing.expectEqual(@as(u8, 4), atlas.data[atlas.size * 2 + 2]); } -test "writing RGB data" { +test "writing BGR data" { const alloc = testing.allocator; - var atlas = try init(alloc, 32, .rgb); + var atlas = try init(alloc, 32, .bgr); defer atlas.deinit(alloc); - // This is RGB so its 3 bpp + // This is BGR so its 3 bpp const reg = try atlas.reserve(alloc, 1, 2); atlas.set(reg, &[_]u8{ 1, 2, 3, @@ -597,18 +610,18 @@ test "writing RGB data" { try testing.expectEqual(@as(u8, 6), atlas.data[65 * depth + 2]); } -test "grow RGB" { +test "grow BGR" { const alloc = testing.allocator; // Atlas is 4x4 so its a 1px border meaning we only have 2x2 available - var atlas = try init(alloc, 4, .rgb); + var atlas = try init(alloc, 4, .bgr); defer atlas.deinit(alloc); // Get our 2x2, which should be ALL our usable space const reg = try atlas.reserve(alloc, 2, 2); try testing.expectError(Error.AtlasFull, atlas.reserve(alloc, 1, 1)); - // This is RGB so its 3 bpp + // This is BGR so its 3 bpp atlas.set(reg, &[_]u8{ 10, 11, 12, // (0, 0) (x, y) from top-left 13, 14, 15, // (1, 0) diff --git a/src/font/face/freetype.zig b/src/font/face/freetype.zig index 9a5f15200..accb891a4 100644 --- a/src/font/face/freetype.zig +++ b/src/font/face/freetype.zig @@ -925,7 +925,7 @@ test "color emoji" { var lib = try Library.init(alloc); defer lib.deinit(); - var atlas = try font.Atlas.init(alloc, 512, .rgba); + var atlas = try font.Atlas.init(alloc, 512, .bgra); defer atlas.deinit(alloc); var ft_font = try Face.init( @@ -973,14 +973,14 @@ test "color emoji" { } } -test "mono to rgba" { +test "mono to bgra" { const alloc = testing.allocator; const testFont = font.embedded.emoji; var lib = try Library.init(alloc); defer lib.deinit(); - var atlas = try font.Atlas.init(alloc, 512, .rgba); + var atlas = try font.Atlas.init(alloc, 512, .bgra); defer atlas.deinit(alloc); var ft_font = try Face.init(lib, testFont, .{ .size = .{ .points = 12, .xdpi = 72, .ydpi = 72 } });