DVUI

tryFromHex

Converts hex color string to Color

Supports the following formats:

  • #RGB
  • #RGBA
  • #RRGGBB
  • #RRGGBBAA
  • RGB
  • RGBA
  • RRGGBB
  • RRGGBBAA

Parameters

#
hex_color:[]const u8
[]const u8

Source

Implementation

#
pub fn tryFromHex(hex_color: []const u8) FromHexError!Color {
    if (hex_color.len == 0) return error.InvalidHexStringLength;
    const hex = if (hex_color[0] == '#') hex_color[1..] else hex_color;

    const is_nibble_size, const has_alpha = switch (hex.len) {
        3 => .{ true, false },
        4 => .{ true, true },
        6 => .{ false, false },
        8 => .{ false, true },
        else => return error.InvalidHexStringLength,
    };
    const num = std.fmt.parseUnsigned(u32, hex, 16) catch |err| switch (err) {
        std.fmt.ParseIntError.Overflow => unreachable, // Length and base is known, cannot overflow
        std.fmt.ParseIntError.InvalidCharacter => |e| return e,
    };

    const mult: u32 = if (is_nibble_size) 0x10 else 1;
    const mask: u32 = if (is_nibble_size) 0xf else 0xff;
    const step: u5 = if (is_nibble_size) 4 else 8;
    const offset: u5 = @intFromBool(has_alpha);
    return .{
        .r = @intCast(mult * ((num >> step * (2 + offset)) & mask)),
        .g = @intCast(mult * ((num >> step * (1 + offset)) & mask)),
        .b = @intCast(mult * ((num >> step * (0 + offset)) & mask)),
        .a = if (has_alpha) @intCast(mult * (num & mask)) else 0xff,
    };
}