From d0677928af54eb3fea5d11db9b593dbc189e854c Mon Sep 17 00:00:00 2001 From: "Jeffrey C. Ollie" Date: Sun, 15 Dec 2024 14:33:09 -0600 Subject: [PATCH] font: add sprites for the separated block quadrants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unicode 16 added "Separated Block Quadrants" from CP 0x0x1CC21 through 0x1CC2F: 𜰡 𜰢 𜰣 𜰤 𜰥 𜰦 𜰧 𜰨 𜰩 𜰪 𜰫 𜰬 𜰭 𜰮 𜰯 To test, use the following command: ``` printf "\U0001CC21\U0001CC22\U0001CC23\U0001CC24\U0001CC25\U0001CC26\U0001CC27\U0001CC28\U0001CC29\U0001CC2A\U0001CC2B\U0001CC2C\U0001CC2D\U0001CC2E\U0001CC2F\n" ``` --- src/font/sprite/Box.zig | 128 +++++++++++++++++++++++++++++++ src/font/sprite/Face.zig | 5 +- src/font/sprite/testdata/Box.ppm | Bin 1048593 -> 1048593 bytes 3 files changed, 132 insertions(+), 1 deletion(-) diff --git a/src/font/sprite/Box.zig b/src/font/sprite/Box.zig index cf929eb67..438af2c4c 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,89 @@ 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 left: f64 = 0.5; + const right = @as(f64, @floatFromInt(self.metrics.cell_width)) - 0.5; + const top: f64 = 0.5; + const bottom = @as(f64, @floatFromInt(self.metrics.cell_height)) - 0.5; + const center_x = @as(f64, @floatFromInt(self.metrics.cell_width)) / 2.0; + const center_left = center_x - 0.5; + const center_right = center_x + 0.5; + const center_y = @as(f64, @floatFromInt(self.metrics.cell_height)) / 2.0; + const center_top = center_y - 0.5; + const center_bottom = center_y + 0.5; + + inline for (fmt) |c| { + switch (c) { + '1' => { + var path = z2d.Path.init(canvas.alloc); + defer path.deinit(); + try path.moveTo(left, top); + try path.lineTo(center_left, top); + try path.lineTo(center_left, center_top); + try path.lineTo(left, center_top); + try path.close(); + try ctx.fill(canvas.alloc, path); + }, + '2' => { + var path = z2d.Path.init(canvas.alloc); + defer path.deinit(); + try path.moveTo(center_right, top); + try path.lineTo(right, top); + try path.lineTo(right, center_top); + try path.lineTo(center_right, center_top); + try path.close(); + try ctx.fill(canvas.alloc, path); + }, + '3' => { + var path = z2d.Path.init(canvas.alloc); + defer path.deinit(); + try path.moveTo(left, center_bottom); + try path.lineTo(center_left, center_bottom); + try path.lineTo(center_left, bottom); + try path.lineTo(left, bottom); + try path.close(); + try ctx.fill(canvas.alloc, path); + }, + '4' => { + var path = z2d.Path.init(canvas.alloc); + defer path.deinit(); + try path.moveTo(center_right, center_bottom); + try path.lineTo(right, center_bottom); + try path.lineTo(right, bottom); + try path.lineTo(center_right, bottom); + try path.close(); + try ctx.fill(canvas.alloc, path); + }, + else => unreachable, + } + } +} + test "all" { const testing = std.testing; const alloc = testing.allocator; @@ -2994,6 +3108,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 1301a4299816fec222672eb24f327db221007b21..331d19502bc75a7ac691d782779325c26ca41b59 100644 GIT binary patch delta 19727 zcmbQ(;4rblp`nGbg{g(Pg{6hHg>4JF{vi(gdI*?q7|JFp1LN564MVnXXKtPkk7$2z2Ojh|3n3s=?DI@il7o=6BYbWMbH!=xMC9()UYV! zVXyxW2Gb2w*u|uwod5L<3~(lt0a73_XjIFM2GoC0j1Y{n(SZ6-YCug?c!4FSjOI0V ziHQnk@O(E>VZvxAA(f4z84a4zWTAnAtrGcPKY77DvFQdE7}=(uKgr2HJ>VAmtmy|z zIdvu~*p8^=gg=y~C(3h3OjpR~WPt|LJ@)?TGwV5JCn|)Gs9+-0B0=Ojq_T-;`h&yl zT+uzwo*5sK`|cMwmqPPbXWF0wt~1N#HU=>Z?u z)rVtDvQD>I0`lY+uqVF^15XkthFGRsuV5G1?*9YiVgDcO8bdx-Co1?%f3S!{6kgJ@ zOt)SG^5P$`7yk@dFRDybm@(ZTgPni+xomdF>HD+U18@;GLo^n_UOe!ZRbcx0W=7ua z1}q%^83);j2uUL}iVxY0rr%%0AqGl}=F{~Lv+GPd!Y(j*KPSS6Oia@+WOMLORM2vP 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 Pax?@+Lx4IVP{08Iw_UdP delta 9610 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