colors with transparency (to fix later)

This commit is contained in:
Jeeves 2024-04-08 12:15:54 -06:00
parent 6e3d7a74be
commit 6065695af9
2 changed files with 98 additions and 64 deletions

View file

@ -18,16 +18,45 @@ pub const RGB = struct {
} }
}; };
// pub const Default256 = [_]RGB{ pub const RGBA = struct {
// RGB{ .r = 0, .g = 0, .b = 0 }, r: f32,
// RGB{ .r = 204, .g = 4, .b = 3 }, g: f32,
// RGB{ .r = 25, .g = 203, .b = 0 }, b: f32,
// RGB{ .r = 206, .g = 203, .b = 0 }, /// Alpha channel between 0.0 - 1.0
// RGB{ .r = 13, .g = 115, .b = 204 }, a: f32 = 1.0,
// RGB{ .r = 203, .g = 30, .b = 209 },
// RGB{ .r = 13, .g = 205, .b = 205 }, /// Create from string at comptime
// RGB{ .r = 221, .g = 221, .b = 221 }, pub fn init(comptime string: []const u8) !RGBA {
// }; std.debug.assert(string.len == 8 or string.len == 9);
comptime var index: usize = 0;
if (string[0] == '#') index += 1;
const r = try fmt.parseInt(u8, string[index .. index + 2], 16);
const g = try fmt.parseInt(u8, string[index + 2 .. index + 4], 16);
const b = try fmt.parseInt(u8, string[index + 4 .. index + 6], 16);
const a = try fmt.parseInt(u8, string[index + 6 .. index + 8], 16);
return .{
.r = @as(f32, @floatFromInt(r)) / 0xff,
.g = @as(f32, @floatFromInt(g)) / 0xff,
.b = @as(f32, @floatFromInt(b)) / 0xff,
.a = @as(f32, @floatFromInt(a)) / 0xff,
};
}
pub fn blend(base: *const RGBA, add: *const RGBA) RGBA {
var r: RGBA = undefined;
r.a = 1 - (1 - add.a) * (1 - base.a);
if (r.a < std.math.floatEps(f32)) {
r.r = 0;
r.g = 0;
r.b = 0;
return r;
}
r.r = (add.r * add.a / r.a + base.r * base.a * (1 - add.a)) / r.a;
r.g = (add.g * add.a / r.a + base.g * base.a * (1 - add.a)) / r.a;
r.b = (add.b * add.a / r.a + base.b * base.a * (1 - add.a)) / r.a;
return r;
}
};
test "RGB init from string" { test "RGB init from string" {
const red = try RGB.init("#ff0000"); const red = try RGB.init("#ff0000");
@ -47,3 +76,18 @@ test "RGB init from string" {
try std.testing.expectError(fmt.ParseIntError.InvalidCharacter, RGB.init("xyzxyz")); try std.testing.expectError(fmt.ParseIntError.InvalidCharacter, RGB.init("xyzxyz"));
} }
test "RGBA blend" {
const red = RGBA{ .r = 1.0, .g = 0, .b = 0, .a = 0.0 };
const blue = RGBA{ .r = 0, .g = 0, .b = 1.0, .a = 0.0 };
const result = red.blend(&blue);
std.debug.print("\n{any}\n", .{result});
const reeb = RGBA{ .r = 1.0, .g = 0, .b = 0, .a = 1.0 };
const blueb = RGBA{ .r = 0, .g = 0, .b = 1.0, .a = 0.0 };
const resultt = reeb.blend(&blueb);
std.debug.print("{any}\n", .{resultt});
const roob = RGBA{ .r = 1.0, .g = 0, .b = 0, .a = 0.5 };
const bloob = RGBA{ .r = 0, .g = 0, .b = 1.0, .a = 0.5 };
const resulttt = roob.blend(&bloob);
std.debug.print("{any}\n", .{resulttt});
}

View file

@ -18,28 +18,27 @@ pub fn main() !void {
var box1 = Terminal.Box.init(allocator); var box1 = Terminal.Box.init(allocator);
defer box1.deinit(); defer box1.deinit();
box1.border_fg = try Terminal.Color.init("#ff8855"); box1.border_bg = try Terminal.Color.init("#3ace37ff");
box1.top = 1; box1.top = 0;
box1.bottom = 1; box1.bottom = 0;
box1.left = 1; box1.left = 0;
box1.right = 1; box1.right = 0;
var box2 = Terminal.Box.init(allocator); var box2 = Terminal.Box.init(allocator);
defer box2.deinit(); defer box2.deinit();
box2.border_fg = try Terminal.Color.init("#aaff55"); box2.border_bg = try Terminal.Color.init("#000000c0");
box2.top = 1; box2.top = 1;
box2.bottom = 1; box2.bottom = 3;
box2.left = 1; box2.left = 20;
box2.right = 1; box2.right = 2;
var box3 = Terminal.Box.init(allocator); var box3 = Terminal.Box.init(allocator);
defer box3.deinit(); defer box3.deinit();
box3.border_bg = try Terminal.Color.init("#aa33ff"); box3.border_bg = try Terminal.Color.init("#48d5eaa0");
box3.border_type = .bg; box3.top = 2;
box3.top = 1;
box3.bottom = 1; box3.bottom = 1;
box3.left = 1; box3.left = 20;
box3.right = 1; box3.right = 20;
try term.box.addChild(&box1); try term.box.addChild(&box1);
try box1.addChild(&box2); try box1.addChild(&box2);
@ -48,38 +47,9 @@ pub fn main() !void {
while (true) { while (true) {
const events = try term.getEvents(); const events = try term.getEvents();
_ = events; _ = events;
// for (events) |ev| if (ev.system == .winch) std.debug.print("hii\n", .{});
try term.draw(); try term.draw();
std.time.sleep(1000); std.time.sleep(1000);
} }
// var box = Terminal.Box{
// .x = 0,
// .y = 0,
// .width = 13,
// .height = 1,
// .content = "hello world",
// .border = true,
// };
// try box.draw(&term);
// try term.clearScreen();
// try term.print("fooboo", .{});
// try term.cursorLeft();
// try term.cursorLeft();
// try term.print("ar", .{});
// // try term.cursorSet(12, 3);
// try term.blinkOn();
// try term.boldOn();
// try term.underlineOn();
// try term.italicsOn();
// try term.print("ABCDEFGHIJKLMNOPQRSTUVWXYZ", .{});
// try term.blinkOff();
// try term.boldOff();
// try term.underlineOff();
// try term.italicsOff();
// try term.print("eeheeveehee\n", .{});
} }
pub const Terminal = struct { pub const Terminal = struct {
@ -289,15 +259,23 @@ pub const Terminal = struct {
// } // }
pub fn setFg(self: *Terminal, color: Color) !void { pub fn setFg(self: *Terminal, color: Color) !void {
try self.info.writeString(.set_rgb_foreground, self.tty.writer(), &[_]u32{ @intCast(color.r), @intCast(color.g), @intCast(color.b) }); try self.info.writeString(.set_rgb_foreground, self.tty.writer(), &[_]u32{
@intFromFloat(color.r * 0xff),
@intFromFloat(color.g * 0xff),
@intFromFloat(color.b * 0xff),
});
} }
pub fn setBg(self: *Terminal, color: Color) !void { pub fn setBg(self: *Terminal, color: Color) !void {
try self.info.writeString(.set_rgb_background, self.tty.writer(), &[_]u32{ @intCast(color.r), @intCast(color.g), @intCast(color.b) }); try self.info.writeString(.set_rgb_background, self.tty.writer(), &[_]u32{
@intFromFloat(color.r * 0xff),
@intFromFloat(color.g * 0xff),
@intFromFloat(color.b * 0xff),
});
} }
pub const Info = @import("terminfo.zig"); pub const Info = @import("terminfo.zig");
pub const Color = @import("color.zig").RGB; pub const Color = @import("color.zig").RGBA;
pub const Box = struct { pub const Box = struct {
parent: ?*Box, parent: ?*Box,
@ -311,10 +289,10 @@ pub const Terminal = struct {
top: u32, top: u32,
bottom: u32, bottom: u32,
border_type: enum { line, bg } = .line, border_type: enum { line, bg } = .bg,
border_char: u8 = ' ', border_char: u8 = ' ',
border_bg: Color = Color{ .r = 0, .g = 0, .b = 0 }, border_bg: Color = Color{ .r = 0.0, .g = 0.0, .b = 0.0 },
border_fg: Color = Color{ .r = 0xff, .g = 0xff, .b = 0xff }, border_fg: Color = Color{ .r = 1.0, .g = 1.0, .b = 1.0 },
content: []const u8 = "", content: []const u8 = "",
@ -369,13 +347,11 @@ pub const Terminal = struct {
pub fn draw(self: *Box, term: *Terminal) !void { pub fn draw(self: *Box, term: *Terminal) !void {
if (self.dirty) { if (self.dirty) {
// if (self != &term.box) self.calcRect();
const rect = self.getRect(); const rect = self.getRect();
// std.debug.print("{any}\r\n", .{rect});
switch (self.border_type) { switch (self.border_type) {
.line => { .line => {
try term.setFg(self.border_fg); try term.setFg(self.getBorderFgColor());
try term.setBg(self.border_bg); try term.setBg(self.getBorderBgColor());
var x: u32 = 0; var x: u32 = 0;
var y: u32 = 0; var y: u32 = 0;
try term.cursorSet(rect.x, rect.y); try term.cursorSet(rect.x, rect.y);
@ -396,7 +372,7 @@ pub const Terminal = struct {
try term.print("", .{}); try term.print("", .{});
}, },
.bg => { .bg => {
try term.setBg(self.border_bg); try term.setBg(self.getBorderBgColor());
var y: u32 = 0; var y: u32 = 0;
try term.cursorSet(rect.x, rect.y); try term.cursorSet(rect.x, rect.y);
while (y < rect.h) : (y += 1) { while (y < rect.h) : (y += 1) {
@ -423,5 +399,19 @@ pub const Terminal = struct {
return rect; return rect;
} }
const Rect = struct { x: u32, y: u32, w: u32, h: u32 }; const Rect = struct { x: u32, y: u32, w: u32, h: u32 };
fn getBorderFgColor(self: *Box) Color {
if (self.parent) |parent| {
const parent_color = parent.getBorderFgColor();
return parent_color.blend(&self.border_fg);
} else return self.border_fg;
}
fn getBorderBgColor(self: *Box) Color {
if (self.parent) |parent| {
const parent_color = parent.getBorderBgColor();
return parent_color.blend(&self.border_bg);
} else return self.border_bg;
}
}; };
}; };