feat: support rendering theme colors with alpha components
This commit is contained in:
parent
3b28286c91
commit
0a43fa853f
9 changed files with 127 additions and 48 deletions
|
@ -22,8 +22,8 @@
|
|||
.hash = "122011f0b0bd6798c0575b7c8f5ec8903fe19509976aedffa5f17c6d98a4dc786de3",
|
||||
},
|
||||
.themes = .{
|
||||
.url = "https://github.com/neurocyte/flow-themes/releases/download/master-d49b4cddde8b33e5a4a60a42a424e836023feb74/flow-themes.tar.gz",
|
||||
.hash = "12206f8cf37aa2b69c30697f06127773899e4155612f4fbf56d9198515513de1cee0",
|
||||
.url = "https://github.com/neurocyte/flow-themes/releases/download/master-5f1ca2fd3c784d430306a5cd1df237681a196333/flow-themes.tar.gz",
|
||||
.hash = "122095b1a6110b920571c7e49e61c124cd9a164fe9b1b0faa1bd11d04d89822d3304",
|
||||
},
|
||||
.fuzzig = .{
|
||||
.url = "https://github.com/fjebaker/fuzzig/archive/0fd156d5097365151e85a85eef9d8cf0eebe7b00.tar.gz",
|
||||
|
|
|
@ -19,6 +19,14 @@ pub const RGB = struct {
|
|||
return r | b | g;
|
||||
}
|
||||
|
||||
pub inline fn from_u8s(v: [3]u8) RGB {
|
||||
return .{ .r = v[0], .g = v[1], .b = v[2] };
|
||||
}
|
||||
|
||||
pub fn to_u8s(v: RGB) [3]u8 {
|
||||
return [_]u8{ v.r, v.g, v.b };
|
||||
}
|
||||
|
||||
pub fn contrast(a_: RGB, b_: RGB) f32 {
|
||||
const a = RGBf.from_RGB(a_).luminance();
|
||||
const b = RGBf.from_RGB(b_).luminance();
|
||||
|
@ -60,3 +68,19 @@ pub const RGBf = struct {
|
|||
pub fn max_contrast(v: u24, a: u24, b: u24) u24 {
|
||||
return RGB.max_contrast(RGB.from_u24(v), RGB.from_u24(a), RGB.from_u24(b)).to_u24();
|
||||
}
|
||||
|
||||
pub fn apply_alpha(base: RGB, over: RGB, alpha_u8: u8) RGB {
|
||||
const alpha: f64 = @as(f64, @floatFromInt(alpha_u8)) / @as(f64, @floatFromInt(0xFF));
|
||||
return .{
|
||||
.r = component_apply_alpha(base.r, over.r, alpha),
|
||||
.g = component_apply_alpha(base.g, over.g, alpha),
|
||||
.b = component_apply_alpha(base.b, over.b, alpha),
|
||||
};
|
||||
}
|
||||
|
||||
inline fn component_apply_alpha(base_u8: u8, over_u8: u8, alpha: f64) u8 {
|
||||
const base: f64 = @floatFromInt(base_u8);
|
||||
const over: f64 = @floatFromInt(over_u8);
|
||||
const result = ((1 - alpha) * base) + (alpha * over);
|
||||
return @intFromFloat(result);
|
||||
}
|
||||
|
|
|
@ -1,14 +1,20 @@
|
|||
const vaxis = @import("vaxis");
|
||||
const Style = @import("theme").Style;
|
||||
const Color = @import("theme").Color;
|
||||
const FontStyle = @import("theme").FontStyle;
|
||||
const color = @import("color");
|
||||
|
||||
const Cell = @This();
|
||||
|
||||
cell: vaxis.Cell = .{},
|
||||
|
||||
pub inline fn set_style(self: *Cell, style_: Style) void {
|
||||
if (style_.fg) |fg| self.cell.style.fg = vaxis.Cell.Color.rgbFromUint(fg);
|
||||
if (style_.bg) |bg| self.cell.style.bg = vaxis.Cell.Color.rgbFromUint(bg);
|
||||
if (style_.fs) |fs| {
|
||||
self.set_style_fg(style_);
|
||||
self.set_style_bg(style_);
|
||||
if (style_.fs) |fs| self.set_font_style(fs);
|
||||
}
|
||||
|
||||
pub inline fn set_font_style(self: *Cell, fs: FontStyle) void {
|
||||
self.cell.style.ul = .default;
|
||||
self.cell.style.ul_style = .off;
|
||||
self.cell.style.bold = false;
|
||||
|
@ -27,19 +33,30 @@ pub inline fn set_style(self: *Cell, style_: Style) void {
|
|||
.undercurl => self.cell.style.ul_style = .curly,
|
||||
.strikethrough => self.cell.style.strikethrough = true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub inline fn set_under_color(self: *Cell, arg_rgb: c_uint) void {
|
||||
self.cell.style.ul = vaxis.Cell.Color.rgbFromUint(@intCast(arg_rgb));
|
||||
}
|
||||
|
||||
inline fn apply_alpha(base_vaxis: vaxis.Cell.Color, over_theme: Color) vaxis.Cell.Color {
|
||||
const alpha = over_theme.alpha;
|
||||
return if (alpha == 0xFF or base_vaxis != .rgb)
|
||||
vaxis.Cell.Color.rgbFromUint(over_theme.color)
|
||||
else blk: {
|
||||
const base = color.RGB.from_u8s(base_vaxis.rgb);
|
||||
const over = color.RGB.from_u24(over_theme.color);
|
||||
const result = color.apply_alpha(base, over, alpha);
|
||||
break :blk .{ .rgb = result.to_u8s() };
|
||||
};
|
||||
}
|
||||
|
||||
pub inline fn set_style_fg(self: *Cell, style_: Style) void {
|
||||
if (style_.fg) |fg| self.cell.style.fg = vaxis.Cell.Color.rgbFromUint(fg);
|
||||
if (style_.fg) |fg| self.cell.style.fg = apply_alpha(self.cell.style.bg, fg);
|
||||
}
|
||||
|
||||
pub inline fn set_style_bg(self: *Cell, style_: Style) void {
|
||||
if (style_.bg) |bg| self.cell.style.bg = vaxis.Cell.Color.rgbFromUint(bg);
|
||||
if (style_.bg) |bg| self.cell.style.bg = apply_alpha(self.cell.style.bg, bg);
|
||||
}
|
||||
|
||||
pub inline fn set_fg_rgb(self: *Cell, arg_rgb: c_uint) !void {
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
const std = @import("std");
|
||||
const Style = @import("theme").Style;
|
||||
const ThemeColor = @import("theme").Color;
|
||||
const FontStyle = @import("theme").FontStyle;
|
||||
const StyleBits = @import("style.zig").StyleBits;
|
||||
const Cell = @import("Cell.zig");
|
||||
const vaxis = @import("vaxis");
|
||||
const Buffer = @import("Buffer");
|
||||
const color = @import("color");
|
||||
const RGB = @import("color").RGB;
|
||||
|
||||
const Plane = @This();
|
||||
|
||||
|
@ -266,12 +269,20 @@ pub fn off_styles(self: *Plane, stylebits: StyleBits) void {
|
|||
if (stylebits.italic) self.style.italic = false;
|
||||
}
|
||||
|
||||
pub fn set_fg_rgb(self: *Plane, channel: u32) !void {
|
||||
self.style.fg = vaxis.Cell.Color.rgbFromUint(@intCast(channel));
|
||||
pub fn set_fg_rgb(self: *Plane, col: ThemeColor) !void {
|
||||
self.style.fg = to_cell_color(col);
|
||||
}
|
||||
|
||||
pub fn set_bg_rgb(self: *Plane, channel: u32) !void {
|
||||
self.style.bg = vaxis.Cell.Color.rgbFromUint(@intCast(channel));
|
||||
pub fn set_fg_rgb_alpha(self: *Plane, alpha_bg: ThemeColor, col: ThemeColor) !void {
|
||||
self.style.fg = apply_alpha_theme(alpha_bg, col);
|
||||
}
|
||||
|
||||
pub fn set_bg_rgb(self: *Plane, col: ThemeColor) !void {
|
||||
self.style.bg = to_cell_color(col);
|
||||
}
|
||||
|
||||
pub fn set_bg_rgb_alpha(self: *Plane, alpha_bg: ThemeColor, col: ThemeColor) !void {
|
||||
self.style.bg = apply_alpha_theme(alpha_bg, col);
|
||||
}
|
||||
|
||||
pub fn set_fg_palindex(self: *Plane, idx: c_uint) !void {
|
||||
|
@ -283,38 +294,54 @@ pub fn set_bg_palindex(self: *Plane, idx: c_uint) !void {
|
|||
}
|
||||
|
||||
pub inline fn set_base_style(self: *Plane, _: [*c]const u8, style_: Style) void {
|
||||
self.style_base.fg = if (style_.fg) |color| vaxis.Cell.Color.rgbFromUint(@intCast(color)) else .default;
|
||||
self.style_base.bg = if (style_.bg) |color| vaxis.Cell.Color.rgbFromUint(@intCast(color)) else .default;
|
||||
self.style_base.fg = if (style_.fg) |col| to_cell_color(col) else .default;
|
||||
self.style_base.bg = if (style_.bg) |col| to_cell_color(col) else .default;
|
||||
if (style_.fs) |fs| set_font_style(&self.style, fs);
|
||||
self.set_style(style_);
|
||||
}
|
||||
|
||||
pub fn set_base_style_transparent(self: *Plane, _: [*:0]const u8, style_: Style) void {
|
||||
self.style_base.fg = if (style_.fg) |color| vaxis.Cell.Color.rgbFromUint(@intCast(color)) else .default;
|
||||
self.style_base.bg = if (style_.bg) |color| vaxis.Cell.Color.rgbFromUint(@intCast(color)) else .default;
|
||||
self.style_base.fg = if (style_.fg) |col| to_cell_color(col) else .default;
|
||||
self.style_base.bg = if (style_.bg) |col| to_cell_color(col) else .default;
|
||||
if (style_.fs) |fs| set_font_style(&self.style, fs);
|
||||
self.set_style(style_);
|
||||
self.transparent = true;
|
||||
}
|
||||
|
||||
pub fn set_base_style_bg_transparent(self: *Plane, _: [*:0]const u8, style_: Style) void {
|
||||
self.style_base.fg = if (style_.fg) |color| vaxis.Cell.Color.rgbFromUint(@intCast(color)) else .default;
|
||||
self.style_base.bg = if (style_.bg) |color| vaxis.Cell.Color.rgbFromUint(@intCast(color)) else .default;
|
||||
self.style_base.fg = if (style_.fg) |col| to_cell_color(col) else .default;
|
||||
self.style_base.bg = if (style_.bg) |col| to_cell_color(col) else .default;
|
||||
if (style_.fs) |fs| set_font_style(&self.style, fs);
|
||||
self.set_style(style_);
|
||||
self.transparent = true;
|
||||
}
|
||||
|
||||
fn apply_alpha(bg: vaxis.Cell.Color, col: ThemeColor) vaxis.Cell.Color {
|
||||
const alpha = col.alpha;
|
||||
return if (alpha == 0xFF or bg != .rgb)
|
||||
.{ .rgb = RGB.to_u8s(RGB.from_u24(col.color)) }
|
||||
else
|
||||
.{ .rgb = color.apply_alpha(RGB.from_u8s(bg.rgb), RGB.from_u24(col.color), alpha).to_u8s() };
|
||||
}
|
||||
|
||||
fn apply_alpha_theme(bg: ThemeColor, col: ThemeColor) vaxis.Cell.Color {
|
||||
const alpha = col.alpha;
|
||||
return if (alpha == 0xFF)
|
||||
.{ .rgb = RGB.to_u8s(RGB.from_u24(col.color)) }
|
||||
else
|
||||
.{ .rgb = color.apply_alpha(RGB.from_u24(bg.color), RGB.from_u24(col.color), alpha).to_u8s() };
|
||||
}
|
||||
|
||||
pub inline fn set_style(self: *Plane, style_: Style) void {
|
||||
if (style_.fg) |color| self.style.fg = vaxis.Cell.Color.rgbFromUint(@intCast(color));
|
||||
if (style_.bg) |color| self.style.bg = vaxis.Cell.Color.rgbFromUint(@intCast(color));
|
||||
if (style_.fg) |col| self.style.fg = apply_alpha(self.style_base.bg, col);
|
||||
if (style_.bg) |col| self.style.bg = apply_alpha(self.style_base.bg, col);
|
||||
if (style_.fs) |fs| set_font_style(&self.style, fs);
|
||||
self.transparent = false;
|
||||
}
|
||||
|
||||
pub inline fn set_style_bg_transparent(self: *Plane, style_: Style) void {
|
||||
if (style_.fg) |color| self.style.fg = vaxis.Cell.Color.rgbFromUint(@intCast(color));
|
||||
if (style_.bg) |color| self.style.bg = vaxis.Cell.Color.rgbFromUint(@intCast(color));
|
||||
if (style_.fg) |col| self.style.fg = apply_alpha(self.style_base.bg, col);
|
||||
if (style_.bg) |col| self.style.bg = apply_alpha(self.style_base.bg, col);
|
||||
if (style_.fs) |fs| set_font_style(&self.style, fs);
|
||||
self.transparent = true;
|
||||
}
|
||||
|
@ -395,3 +422,7 @@ const GraphemeCache = struct {
|
|||
return self.buf[self.idx .. self.idx + bytes.len];
|
||||
}
|
||||
};
|
||||
|
||||
fn to_cell_color(col: ThemeColor) vaxis.Cell.Color {
|
||||
return .{ .rgb = RGB.to_u8s(RGB.from_u24(col.color)) };
|
||||
}
|
||||
|
|
|
@ -329,9 +329,9 @@ pub fn set_terminal_title(self: *Self, text: []const u8) void {
|
|||
|
||||
pub fn set_terminal_style(self: *Self, style_: Style) void {
|
||||
if (style_.fg) |color|
|
||||
self.vx.setTerminalForegroundColor(self.tty.anyWriter(), vaxis.Cell.Color.rgbFromUint(@intCast(color)).rgb) catch {};
|
||||
self.vx.setTerminalForegroundColor(self.tty.anyWriter(), vaxis.Cell.Color.rgbFromUint(@intCast(color.color)).rgb) catch {};
|
||||
if (style_.bg) |color|
|
||||
self.vx.setTerminalBackgroundColor(self.tty.anyWriter(), vaxis.Cell.Color.rgbFromUint(@intCast(color)).rgb) catch {};
|
||||
self.vx.setTerminalBackgroundColor(self.tty.anyWriter(), vaxis.Cell.Color.rgbFromUint(@intCast(color.color)).rgb) catch {};
|
||||
}
|
||||
|
||||
pub fn set_terminal_working_directory(self: *Self, absolute_path: []const u8) void {
|
||||
|
|
|
@ -960,7 +960,7 @@ pub const Editor = struct {
|
|||
var cell = self.plane.cell_init();
|
||||
_ = self.plane.at_cursor_cell(&cell) catch return;
|
||||
cell.set_style(.{ .fs = .undercurl });
|
||||
if (style.fg) |ul_col| cell.set_under_color(ul_col);
|
||||
if (style.fg) |ul_col| cell.set_under_color(ul_col.color);
|
||||
_ = self.plane.putc(&cell) catch {};
|
||||
}
|
||||
|
||||
|
|
|
@ -161,10 +161,10 @@ pub fn render_linear(self: *Self, theme: *const Widget.Theme) void {
|
|||
while (rows > 0) : (rows -= 1) {
|
||||
if (linenum > self.lines) return;
|
||||
if (linenum == self.line + 1) {
|
||||
self.plane.set_base_style(" ", theme.editor_gutter_active);
|
||||
self.plane.set_style(theme.editor_gutter_active);
|
||||
self.plane.on_styles(style.bold);
|
||||
} else {
|
||||
self.plane.set_base_style(" ", theme.editor_gutter);
|
||||
self.plane.set_style(theme.editor_gutter);
|
||||
self.plane.off_styles(style.bold);
|
||||
}
|
||||
_ = self.plane.print_aligned_right(@intCast(pos), "{s}", .{std.fmt.bufPrintZ(&buf, "{d} ", .{linenum}) catch return}) catch {};
|
||||
|
@ -187,7 +187,7 @@ pub fn render_relative(self: *Self, theme: *const Widget.Theme) void {
|
|||
var buf: [31:0]u8 = undefined;
|
||||
while (rows > 0) : (rows -= 1) {
|
||||
if (pos > self.lines - @as(u32, @intCast(row))) return;
|
||||
self.plane.set_base_style(" ", if (linenum == 0) theme.editor_gutter_active else theme.editor_gutter);
|
||||
self.plane.set_style(if (linenum == 0) theme.editor_gutter_active else theme.editor_gutter);
|
||||
const val = @abs(if (linenum == 0) line else linenum);
|
||||
const fmt = std.fmt.bufPrintZ(&buf, "{d} ", .{val}) catch return;
|
||||
_ = self.plane.print_aligned_right(@intCast(pos), "{s}", .{if (fmt.len > 6) "==> " else fmt}) catch {};
|
||||
|
|
|
@ -157,9 +157,15 @@ fn show_color(self: *Self, tag: []const u8, c_: ?Widget.Theme.Color) void {
|
|||
if (c_) |c| {
|
||||
_ = self.plane.print(" {s}:", .{tag}) catch return;
|
||||
self.plane.set_bg_rgb(c) catch {};
|
||||
self.plane.set_fg_rgb(color.max_contrast(c, theme.panel.fg orelse 0xFFFFFF, theme.panel.bg orelse 0x000000)) catch {};
|
||||
_ = self.plane.print("#{x}", .{c}) catch return;
|
||||
self.plane.set_fg_rgb(.{ .color = color.max_contrast(
|
||||
c.color,
|
||||
(theme.panel.fg orelse Widget.Theme.Color{ .color = 0xFFFFFF }).color,
|
||||
(theme.panel.bg orelse Widget.Theme.Color{ .color = 0x000000 }).color,
|
||||
) }) catch {};
|
||||
_ = self.plane.print("#{x}", .{c.color}) catch return;
|
||||
self.reset_style();
|
||||
if (c.alpha != 0xff)
|
||||
_ = self.plane.print(" ɑ{x}", .{c.alpha}) catch return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -61,8 +61,9 @@ pub fn render(_: *void, self: *Button.State(void), theme: *const Widget.Theme) b
|
|||
}
|
||||
|
||||
fn render_separator(self: *Button.State(void), theme: *const Widget.Theme) void {
|
||||
if (theme.statusbar_hover.bg) |bg| self.plane.set_fg_rgb(bg) catch {};
|
||||
if (theme.statusbar.bg) |bg| self.plane.set_bg_rgb(bg) catch {};
|
||||
const statusbar_bg = theme.statusbar.bg orelse theme.editor.bg.?;
|
||||
if (theme.statusbar_hover.bg) |bg| self.plane.set_fg_rgb_alpha(statusbar_bg, bg) catch {};
|
||||
if (theme.statusbar.bg) |bg| self.plane.set_bg_rgb_alpha(statusbar_bg, bg) catch {};
|
||||
_ = self.plane.putstr("") catch {};
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue