From dfefe953fcb1b647e5fd9fac0013a634b8bcff65 Mon Sep 17 00:00:00 2001 From: Chris Marchesi Date: Tue, 19 Dec 2023 11:36:05 -0800 Subject: [PATCH] Powerline: add trapezoid rendering This adds Powerline rendering for the trapezoid characters (E0D2 and E0D4). This is the last of the Powerline additions for now. These are the shapes that 1) render the most egregiously with stock fonts (off-center, bleeding background, visible gaps), and 2) are simple enough to be rendered without resorting to more complex measures like embedding SVG. --- src/font/sprite/Face.zig | 2 + src/font/sprite/Powerline.zig | 115 ++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+) diff --git a/src/font/sprite/Face.zig b/src/font/sprite/Face.zig index d897b1341..86dd70c71 100644 --- a/src/font/sprite/Face.zig +++ b/src/font/sprite/Face.zig @@ -181,6 +181,8 @@ const Kind = enum { 0xE0BA, 0xE0BC, 0xE0BE, + 0xE0D2, + 0xE0D4, => .powerline, else => null, diff --git a/src/font/sprite/Powerline.zig b/src/font/sprite/Powerline.zig index 642ecdad2..a6551b5f3 100644 --- a/src/font/sprite/Powerline.zig +++ b/src/font/sprite/Powerline.zig @@ -11,6 +11,7 @@ const std = @import("std"); const Allocator = std.mem.Allocator; const font = @import("../main.zig"); +const Trapezoid = @import("canvas.zig").Trapezoid; const log = std.log.scoped(.powerline_font); @@ -97,6 +98,11 @@ fn draw(self: Powerline, alloc: Allocator, canvas: *font.sprite.Canvas, cp: u32) 0xE0B6, => try self.draw_half_circle(alloc, canvas, cp), + // Mirrored top-down trapezoids + 0xE0D2, + 0xE0D4, + => try self.draw_trapezoid_top_bottom(canvas, cp), + else => return error.InvalidCodepoint, } } @@ -397,6 +403,113 @@ fn draw_half_circle(self: Powerline, alloc: Allocator, canvas: *font.sprite.Canv } } +fn draw_trapezoid_top_bottom(self: Powerline, canvas: *font.sprite.Canvas, cp: u32) !void { + const t_top: Trapezoid = if (cp == 0xE0D4) + .{ + .top = 0, + .bottom = @intCast(self.height / 2 - self.height / 20), + .left = .{ + .p1 = .{ + .x = 0, + .y = 0, + }, + .p2 = .{ + .x = @intCast(self.width - self.width / 3), + .y = @intCast(self.height / 2 - self.height / 20), + }, + }, + .right = .{ + .p1 = .{ + .x = @intCast(self.width), + .y = 0, + }, + .p2 = .{ + .x = @intCast(self.width), + .y = @intCast(self.height / 2 - self.height / 20), + }, + }, + } + else + .{ + .top = 0, + .bottom = @intCast(self.height / 2 - self.height / 20), + .left = .{ + .p1 = .{ + .x = 0, + .y = 0, + }, + .p2 = .{ + .x = 0, + .y = @intCast(self.height / 2 - self.height / 20), + }, + }, + .right = .{ + .p1 = .{ + .x = @intCast(self.width), + .y = 0, + }, + .p2 = .{ + .x = @intCast(self.width / 3), + .y = @intCast(self.height / 2 - self.height / 20), + }, + }, + }; + + const t_bottom: Trapezoid = if (cp == 0xE0D4) + .{ + .top = @intCast(self.height / 2 + self.height / 20), + .bottom = @intCast(self.height), + .left = .{ + .p1 = .{ + .x = @intCast(self.width - self.width / 3), + .y = @intCast(self.height / 2 + self.height / 20), + }, + .p2 = .{ + .x = 0, + .y = @intCast(self.height), + }, + }, + .right = .{ + .p1 = .{ + .x = @intCast(self.width), + .y = @intCast(self.height / 2 + self.height / 20), + }, + .p2 = .{ + .x = @intCast(self.width), + .y = @intCast(self.height), + }, + }, + } + else + .{ + .top = @intCast(self.height / 2 + self.height / 20), + .bottom = @intCast(self.height), + .left = .{ + .p1 = .{ + .x = 0, + .y = @intCast(self.height / 2 + self.height / 20), + }, + .p2 = .{ + .x = 0, + .y = @intCast(self.height), + }, + }, + .right = .{ + .p1 = .{ + .x = @intCast(self.width / 3), + .y = @intCast(self.height / 2 + self.height / 20), + }, + .p2 = .{ + .x = @intCast(self.width), + .y = @intCast(self.height), + }, + }, + }; + + canvas.trapezoid(t_top); + canvas.trapezoid(t_bottom); +} + test "all" { const testing = std.testing; const alloc = testing.allocator; @@ -410,6 +523,8 @@ test "all" { 0xE0BE, 0xE0B4, 0xE0B6, + 0xE0D2, + 0xE0D4, }; for (cps) |cp| { var atlas_greyscale = try font.Atlas.init(alloc, 512, .greyscale);