diff --git a/.gitignore b/.gitignore index c7a2cf20b..0e301f8c4 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ test/ghostty test/cases/**/*.actual.png glad.zip +/Box_test.ppm +/Box_test_diff.ppm diff --git a/src/font/sprite/Box.zig b/src/font/sprite/Box.zig index cf929eb67..f48b50598 100644 --- a/src/font/sprite/Box.zig +++ b/src/font/sprite/Box.zig @@ -1624,6 +1624,37 @@ fn draw(self: Box, alloc: Allocator, canvas: *font.sprite.Canvas, cp: u32) !void .right = true, }, .light), + // '𜰡' - SEPARATED BLOCK QUADRANT-1 + 0x1cc21 => try self.draw_separated_block_quadrant(canvas, "1"), + // '𜰢' - SEPARATED BLOCK QUADRANT-2 + 0x1cc22 => try self.draw_separated_block_quadrant(canvas, "2"), + // '𜰣' - SEPARATED BLOCK QUADRANT-12 + 0x1cc23 => try self.draw_separated_block_quadrant(canvas, "12"), + // '𜰤' - SEPARATED BLOCK QUADRANT-3 + 0x1cc24 => try self.draw_separated_block_quadrant(canvas, "3"), + // '𜰥' - SEPARATED BLOCK QUADRANT-13 + 0x1cc25 => try self.draw_separated_block_quadrant(canvas, "13"), + // '𜰦' - SEPARATED BLOCK QUADRANT-23 + 0x1cc26 => try self.draw_separated_block_quadrant(canvas, "23"), + // '𜰧' - SEPARATED BLOCK QUADRANT-123 + 0x1cc27 => try self.draw_separated_block_quadrant(canvas, "123"), + // '𜰨' - SEPARATED BLOCK QUADRANT-4 + 0x1cc28 => try self.draw_separated_block_quadrant(canvas, "4"), + // '𜰩' - SEPARATED BLOCK QUADRANT-14 + 0x1cc29 => try self.draw_separated_block_quadrant(canvas, "14"), + // '𜰪' - SEPARATED BLOCK QUADRANT-24 + 0x1cc2a => try self.draw_separated_block_quadrant(canvas, "24"), + // '𜰫' - SEPARATED BLOCK QUADRANT-124 + 0x1cc2b => try self.draw_separated_block_quadrant(canvas, "124"), + // '𜰬' - SEPARATED BLOCK QUADRANT-34 + 0x1cc2c => try self.draw_separated_block_quadrant(canvas, "34"), + // '𜰭' - SEPARATED BLOCK QUADRANT-134 + 0x1cc2d => try self.draw_separated_block_quadrant(canvas, "134"), + // '𜰮' - SEPARATED BLOCK QUADRANT-234 + 0x1cc2e => try self.draw_separated_block_quadrant(canvas, "234"), + // '𜰯' - SEPARATED BLOCK QUADRANT-1234 + 0x1cc2f => try self.draw_separated_block_quadrant(canvas, "1234"), + else => return error.InvalidCodepoint, } } @@ -2865,6 +2896,74 @@ fn rect( } }).rect(), .on); } +// Separated Block Quadrants from Symbols for Legacy Computing Supplement +// 𜰡 𜰢 𜰣 𜰤 𜰥 𜰦 𜰧 𜰨 𜰩 𜰪 𜰫 𜰬 𜰭 𜰮 𜰯 +fn draw_separated_block_quadrant(self: Box, canvas: *font.sprite.Canvas, comptime fmt: []const u8) !void { + comptime { + if (fmt.len > 4) @compileError("cannot have more than four quadrants"); + var seen = [_]bool{false} ** (std.math.maxInt(u8) + 1); + for (fmt) |c| { + if (seen[c]) @compileError("repeated quadrants not allowed"); + seen[c] = true; + switch (c) { + '1'...'4' => {}, + else => @compileError("invalid quadrant"), + } + } + } + + var ctx: z2d.Context = .{ + .surface = canvas.sfc, + .pattern = .{ + .opaque_pattern = .{ + .pixel = .{ .alpha8 = .{ .a = @intFromEnum(Shade.on) } }, + }, + }, + }; + + const gap: f64 = @max(1.0, @as(f64, @floatFromInt(self.metrics.cell_width)) * 0.10) / 2.0; + const left: f64 = gap; + const right = @as(f64, @floatFromInt(self.metrics.cell_width)) - gap; + const top: f64 = gap; + const bottom = @as(f64, @floatFromInt(self.metrics.cell_height)) - gap; + const center_x = @as(f64, @floatFromInt(self.metrics.cell_width)) / 2.0; + const center_left = center_x - gap; + const center_right = center_x + gap; + const center_y = @as(f64, @floatFromInt(self.metrics.cell_height)) / 2.0; + const center_top = center_y - gap; + const center_bottom = center_y + gap; + + inline for (fmt) |c| { + const x1, const y1, const x2, const y2 = switch (c) { + '1' => .{ + left, top, + center_left, center_top, + }, + '2' => .{ + center_right, top, + right, center_top, + }, + '3' => .{ + left, center_bottom, + center_left, bottom, + }, + '4' => .{ + center_right, center_bottom, + right, bottom, + }, + else => unreachable, + }; + var path = z2d.Path.init(canvas.alloc); + defer path.deinit(); + try path.moveTo(x1, y1); + try path.lineTo(x2, y1); + try path.lineTo(x2, y2); + try path.lineTo(x1, y2); + try path.close(); + try ctx.fill(canvas.alloc, path); + } +} + test "all" { const testing = std.testing; const alloc = testing.allocator; @@ -2994,6 +3093,20 @@ fn testRenderAll(self: Box, alloc: Allocator, atlas: *font.Atlas) !void { cp, ); } + + // Symbols for Legacy Computing Supplement. + // 𜰡 𜰢 𜰣 𜰤 𜰥 𜰦 𜰧 𜰨 𜰩 𜰪 𜰫 𜰬 𜰭 𜰮 𜰯 + cp = 0x1cc21; + while (cp <= 0x1cc2f) : (cp += 1) { + switch (cp) { + 0x1cc21...0x1cc2f => _ = try self.renderGlyph( + alloc, + atlas, + cp, + ), + else => {}, + } + } } test "render all sprites" { diff --git a/src/font/sprite/Face.zig b/src/font/sprite/Face.zig index ede67d00d..83dfffefa 100644 --- a/src/font/sprite/Face.zig +++ b/src/font/sprite/Face.zig @@ -152,7 +152,6 @@ pub fn renderGlyph( break :cursor g; }, - }; } @@ -263,6 +262,10 @@ const Kind = enum { //             0xF5D0...0xF60D => .box, + // Separated Block Quadrants from Symbols for Legacy Computing Supplement + // 𜰡 𜰢 𜰣 𜰤 𜰥 𜰦 𜰧 𜰨 𜰩 𜰪 𜰫 𜰬 𜰭 𜰮 𜰯 + 0x1CC21...0x1CC2F => .box, + // Powerline fonts 0xE0B0, 0xE0B1, diff --git a/src/font/sprite/testdata/Box.ppm b/src/font/sprite/testdata/Box.ppm index 1301a4299..56d190842 100644 Binary files a/src/font/sprite/testdata/Box.ppm and b/src/font/sprite/testdata/Box.ppm differ