tiny.css.value.color
Defined in value.
API (11)
Actions
Public operations.
alpha: The alpha channel of a packed colour.blue: The blue channel of a packed colour.function: Parses the argument list ofrgb(),rgba(),hsl(), orhsla().green: The green channel of a packed colour.hex: Parses a#rgb,#rgba,#rrggbb, or#rrggbbaabody without its hash.named: Resolves a named colour, ASCII case insensitively.pack: Packs eight bit channels into theaword of a colour value.red: The red channel of a packed colour.
Types and contracts
Public types and contracts.
Named: One CSS Color 4 named colour and its packed value.
Values and defaults
Public values and defaults.
names: The CSS Color 4 named colours, sorted so that lookup is a binary search.transparent: Fully transparent black, which is whattransparentcomputes to.
Source
Source: lib/css/src/value/color.zig
zig
const std = @import("std");/// One CSS Color 4 named colour and its packed value.pub const Named = struct { name: []const u8, rgba: u32,};/// Packs eight bit channels into the `a` word of a colour value.pub fn pack(red_channel: u8, green_channel: u8, blue_channel: u8, alpha_channel: u8) u32 { return (@as(u32, red_channel) << 24) | (@as(u32, green_channel) << 16) | (@as(u32, blue_channel) << 8) | @as(u32, alpha_channel);}/// The red channel of a packed colour.pub fn red(rgba: u32) u8 { return @truncate(rgba >> 24);}/// The green channel of a packed colour.pub fn green(rgba: u32) u8 { return @truncate(rgba >> 16);}/// The blue channel of a packed colour.pub fn blue(rgba: u32) u8 { return @truncate(rgba >> 8);}/// The alpha channel of a packed colour.pub fn alpha(rgba: u32) u8 { return @truncate(rgba);}/// Fully transparent black, which is what `transparent` computes to.pub const transparent: u32 = 0;/// The CSS Color 4 named colours, sorted so that lookup is a binary search.pub const names = [_]Named{ .{ .name = "aliceblue", .rgba = 0xF0F8FFFF }, .{ .name = "antiquewhite", .rgba = 0xFAEBD7FF }, .{ .name = "aqua", .rgba = 0x00FFFFFF }, .{ .name = "aquamarine", .rgba = 0x7FFFD4FF }, .{ .name = "azure", .rgba = 0xF0FFFFFF }, .{ .name = "beige", .rgba = 0xF5F5DCFF }, .{ .name = "bisque", .rgba = 0xFFE4C4FF }, .{ .name = "black", .rgba = 0x000000FF }, .{ .name = "blanchedalmond", .rgba = 0xFFEBCDFF }, .{ .name = "blue", .rgba = 0x0000FFFF }, .{ .name = "blueviolet", .rgba = 0x8A2BE2FF }, .{ .name = "brown", .rgba = 0xA52A2AFF }, .{ .name = "burlywood", .rgba = 0xDEB887FF }, .{ .name = "cadetblue", .rgba = 0x5F9EA0FF }, .{ .name = "chartreuse", .rgba = 0x7FFF00FF }, .{ .name = "chocolate", .rgba = 0xD2691EFF }, .{ .name = "coral", .rgba = 0xFF7F50FF }, .{ .name = "cornflowerblue", .rgba = 0x6495EDFF }, .{ .name = "cornsilk", .rgba = 0xFFF8DCFF }, .{ .name = "crimson", .rgba = 0xDC143CFF }, .{ .name = "cyan", .rgba = 0x00FFFFFF }, .{ .name = "darkblue", .rgba = 0x00008BFF }, .{ .name = "darkcyan", .rgba = 0x008B8BFF }, .{ .name = "darkgoldenrod", .rgba = 0xB8860BFF }, .{ .name = "darkgray", .rgba = 0xA9A9A9FF }, .{ .name = "darkgreen", .rgba = 0x006400FF }, .{ .name = "darkgrey", .rgba = 0xA9A9A9FF }, .{ .name = "darkkhaki", .rgba = 0xBDB76BFF }, .{ .name = "darkmagenta", .rgba = 0x8B008BFF }, .{ .name = "darkolivegreen", .rgba = 0x556B2FFF }, .{ .name = "darkorange", .rgba = 0xFF8C00FF }, .{ .name = "darkorchid", .rgba = 0x9932CCFF }, .{ .name = "darkred", .rgba = 0x8B0000FF }, .{ .name = "darksalmon", .rgba = 0xE9967AFF }, .{ .name = "darkseagreen", .rgba = 0x8FBC8FFF }, .{ .name = "darkslateblue", .rgba = 0x483D8BFF }, .{ .name = "darkslategray", .rgba = 0x2F4F4FFF }, .{ .name = "darkslategrey", .rgba = 0x2F4F4FFF }, .{ .name = "darkturquoise", .rgba = 0x00CED1FF }, .{ .name = "darkviolet", .rgba = 0x9400D3FF }, .{ .name = "deeppink", .rgba = 0xFF1493FF }, .{ .name = "deepskyblue", .rgba = 0x00BFFFFF }, .{ .name = "dimgray", .rgba = 0x696969FF }, .{ .name = "dimgrey", .rgba = 0x696969FF }, .{ .name = "dodgerblue", .rgba = 0x1E90FFFF }, .{ .name = "firebrick", .rgba = 0xB22222FF }, .{ .name = "floralwhite", .rgba = 0xFFFAF0FF }, .{ .name = "forestgreen", .rgba = 0x228B22FF }, .{ .name = "fuchsia", .rgba = 0xFF00FFFF }, .{ .name = "gainsboro", .rgba = 0xDCDCDCFF }, .{ .name = "ghostwhite", .rgba = 0xF8F8FFFF }, .{ .name = "gold", .rgba = 0xFFD700FF }, .{ .name = "goldenrod", .rgba = 0xDAA520FF }, .{ .name = "gray", .rgba = 0x808080FF }, .{ .name = "green", .rgba = 0x008000FF }, .{ .name = "greenyellow", .rgba = 0xADFF2FFF }, .{ .name = "grey", .rgba = 0x808080FF }, .{ .name = "honeydew", .rgba = 0xF0FFF0FF }, .{ .name = "hotpink", .rgba = 0xFF69B4FF }, .{ .name = "indianred", .rgba = 0xCD5C5CFF }, .{ .name = "indigo", .rgba = 0x4B0082FF }, .{ .name = "ivory", .rgba = 0xFFFFF0FF }, .{ .name = "khaki", .rgba = 0xF0E68CFF }, .{ .name = "lavender", .rgba = 0xE6E6FAFF }, .{ .name = "lavenderblush", .rgba = 0xFFF0F5FF }, .{ .name = "lawngreen", .rgba = 0x7CFC00FF }, .{ .name = "lemonchiffon", .rgba = 0xFFFACDFF }, .{ .name = "lightblue", .rgba = 0xADD8E6FF }, .{ .name = "lightcoral", .rgba = 0xF08080FF }, .{ .name = "lightcyan", .rgba = 0xE0FFFFFF }, .{ .name = "lightgoldenrodyellow", .rgba = 0xFAFAD2FF }, .{ .name = "lightgray", .rgba = 0xD3D3D3FF }, .{ .name = "lightgreen", .rgba = 0x90EE90FF }, .{ .name = "lightgrey", .rgba = 0xD3D3D3FF }, .{ .name = "lightpink", .rgba = 0xFFB6C1FF }, .{ .name = "lightsalmon", .rgba = 0xFFA07AFF }, .{ .name = "lightseagreen", .rgba = 0x20B2AAFF }, .{ .name = "lightskyblue", .rgba = 0x87CEFAFF }, .{ .name = "lightslategray", .rgba = 0x778899FF }, .{ .name = "lightslategrey", .rgba = 0x778899FF }, .{ .name = "lightsteelblue", .rgba = 0xB0C4DEFF }, .{ .name = "lightyellow", .rgba = 0xFFFFE0FF }, .{ .name = "lime", .rgba = 0x00FF00FF }, .{ .name = "limegreen", .rgba = 0x32CD32FF }, .{ .name = "linen", .rgba = 0xFAF0E6FF }, .{ .name = "magenta", .rgba = 0xFF00FFFF }, .{ .name = "maroon", .rgba = 0x800000FF }, .{ .name = "mediumaquamarine", .rgba = 0x66CDAAFF }, .{ .name = "mediumblue", .rgba = 0x0000CDFF }, .{ .name = "mediumorchid", .rgba = 0xBA55D3FF }, .{ .name = "mediumpurple", .rgba = 0x9370DBFF }, .{ .name = "mediumseagreen", .rgba = 0x3CB371FF }, .{ .name = "mediumslateblue", .rgba = 0x7B68EEFF }, .{ .name = "mediumspringgreen", .rgba = 0x00FA9AFF }, .{ .name = "mediumturquoise", .rgba = 0x48D1CCFF }, .{ .name = "mediumvioletred", .rgba = 0xC71585FF }, .{ .name = "midnightblue", .rgba = 0x191970FF }, .{ .name = "mintcream", .rgba = 0xF5FFFAFF }, .{ .name = "mistyrose", .rgba = 0xFFE4E1FF }, .{ .name = "moccasin", .rgba = 0xFFE4B5FF }, .{ .name = "navajowhite", .rgba = 0xFFDEADFF }, .{ .name = "navy", .rgba = 0x000080FF }, .{ .name = "oldlace", .rgba = 0xFDF5E6FF }, .{ .name = "olive", .rgba = 0x808000FF }, .{ .name = "olivedrab", .rgba = 0x6B8E23FF }, .{ .name = "orange", .rgba = 0xFFA500FF }, .{ .name = "orangered", .rgba = 0xFF4500FF }, .{ .name = "orchid", .rgba = 0xDA70D6FF }, .{ .name = "palegoldenrod", .rgba = 0xEEE8AAFF }, .{ .name = "palegreen", .rgba = 0x98FB98FF }, .{ .name = "paleturquoise", .rgba = 0xAFEEEEFF }, .{ .name = "palevioletred", .rgba = 0xDB7093FF }, .{ .name = "papayawhip", .rgba = 0xFFEFD5FF }, .{ .name = "peachpuff", .rgba = 0xFFDAB9FF }, .{ .name = "peru", .rgba = 0xCD853FFF }, .{ .name = "pink", .rgba = 0xFFC0CBFF }, .{ .name = "plum", .rgba = 0xDDA0DDFF }, .{ .name = "powderblue", .rgba = 0xB0E0E6FF }, .{ .name = "purple", .rgba = 0x800080FF }, .{ .name = "rebeccapurple", .rgba = 0x663399FF }, .{ .name = "red", .rgba = 0xFF0000FF }, .{ .name = "rosybrown", .rgba = 0xBC8F8FFF }, .{ .name = "royalblue", .rgba = 0x4169E1FF }, .{ .name = "saddlebrown", .rgba = 0x8B4513FF }, .{ .name = "salmon", .rgba = 0xFA8072FF }, .{ .name = "sandybrown", .rgba = 0xF4A460FF }, .{ .name = "seagreen", .rgba = 0x2E8B57FF }, .{ .name = "seashell", .rgba = 0xFFF5EEFF }, .{ .name = "sienna", .rgba = 0xA0522DFF }, .{ .name = "silver", .rgba = 0xC0C0C0FF }, .{ .name = "skyblue", .rgba = 0x87CEEBFF }, .{ .name = "slateblue", .rgba = 0x6A5ACDFF }, .{ .name = "slategray", .rgba = 0x708090FF }, .{ .name = "slategrey", .rgba = 0x708090FF }, .{ .name = "snow", .rgba = 0xFFFAFAFF }, .{ .name = "springgreen", .rgba = 0x00FF7FFF }, .{ .name = "steelblue", .rgba = 0x4682B4FF }, .{ .name = "tan", .rgba = 0xD2B48CFF }, .{ .name = "teal", .rgba = 0x008080FF }, .{ .name = "thistle", .rgba = 0xD8BFD8FF }, .{ .name = "tomato", .rgba = 0xFF6347FF }, .{ .name = "turquoise", .rgba = 0x40E0D0FF }, .{ .name = "violet", .rgba = 0xEE82EEFF }, .{ .name = "wheat", .rgba = 0xF5DEB3FF }, .{ .name = "white", .rgba = 0xFFFFFFFF }, .{ .name = "whitesmoke", .rgba = 0xF5F5F5FF }, .{ .name = "yellow", .rgba = 0xFFFF00FF }, .{ .name = "yellowgreen", .rgba = 0x9ACD32FF },};comptime { @setEvalBranchQuota(16_000); for (names[1..], 1..) |entry, index| { if (!(std.mem.order(u8, names[index - 1].name, entry.name) == .lt)) { @compileError("named colours must stay sorted for binary search"); } }}/// Resolves a named colour, ASCII case insensitively.pub fn named(name: []const u8) ?u32 { if (name.len == 0 or name.len > 24) return null; var buffer: [24]u8 = undefined; for (name, 0..) |byte, index| buffer[index] = std.ascii.toLower(byte); const folded = buffer[0..name.len]; var low: usize = 0; var high: usize = names.len; while (low < high) { const middle = low + (high - low) / 2; switch (std.mem.order(u8, names[middle].name, folded)) { .lt => low = middle + 1, .gt => high = middle, .eq => return names[middle].rgba, } } return null;}/// Parses a `#rgb`, `#rgba`, `#rrggbb`, or `#rrggbbaa` body without its hash.pub fn hex(digits: []const u8) ?u32 { for (digits) |byte| { if (!std.ascii.isHex(byte)) return null; } return switch (digits.len) { 3 => pack(expand(digits[0]), expand(digits[1]), expand(digits[2]), 255), 4 => pack(expand(digits[0]), expand(digits[1]), expand(digits[2]), expand(digits[3])), 6 => pack(pair(digits[0..2]), pair(digits[2..4]), pair(digits[4..6]), 255), 8 => pack(pair(digits[0..2]), pair(digits[2..4]), pair(digits[4..6]), pair(digits[6..8])), else => null, };}/// Parses the argument list of `rgb()`, `rgba()`, `hsl()`, or `hsla()`.pub fn function(name: []const u8, arguments: []const u8) ?u32 { var parts: [4][]const u8 = undefined; const count = split(arguments, &parts); if (count < 3) return null; if (std.ascii.eqlIgnoreCase(name, "rgb") or std.ascii.eqlIgnoreCase(name, "rgba")) { return pack( channel(parts[0]) orelse return null, channel(parts[1]) orelse return null, channel(parts[2]) orelse return null, if (count == 4) opacity(parts[3]) orelse return null else 255, ); } if (std.ascii.eqlIgnoreCase(name, "hsl") or std.ascii.eqlIgnoreCase(name, "hsla")) { const hue = scalar(parts[0]) orelse return null; const saturation = ratio(parts[1]) orelse return null; const lightness = ratio(parts[2]) orelse return null; const opaque_alpha = if (count == 4) opacity(parts[3]) orelse return null else 255; return fromHsl(hue, saturation, lightness, opaque_alpha); } return null;}fn expand(digit: u8) u8 { const value = digitValue(digit); return value * 17;}fn pair(digits: []const u8) u8 { return digitValue(digits[0]) * 16 + digitValue(digits[1]);}fn digitValue(digit: u8) u8 { if (digit <= '9') return digit - '0'; return (digit | 0x20) - 'a' + 10;}fn split(arguments: []const u8, parts: *[4][]const u8) usize { var count: usize = 0; var iterator = std.mem.tokenizeAny(u8, arguments, ", \t\r\n/"); while (iterator.next()) |part| { if (count == parts.len) return count + 1; parts[count] = part; count += 1; } return count;}fn scalar(text: []const u8) ?f32 { var body = text; if (std.mem.endsWith(u8, body, "deg")) body = body[0 .. body.len - 3]; return std.fmt.parseFloat(f32, body) catch null;}fn channel(text: []const u8) ?u8 { if (std.mem.endsWith(u8, text, "%")) { const fraction = std.fmt.parseFloat(f32, text[0 .. text.len - 1]) catch return null; return clamp(fraction * 255.0 / 100.0); } const value = std.fmt.parseFloat(f32, text) catch return null; return clamp(value);}fn opacity(text: []const u8) ?u8 { if (std.mem.endsWith(u8, text, "%")) { const fraction = std.fmt.parseFloat(f32, text[0 .. text.len - 1]) catch return null; return clamp(fraction * 255.0 / 100.0); } const value = std.fmt.parseFloat(f32, text) catch return null; return clamp(value * 255.0);}fn ratio(text: []const u8) ?f32 { if (!std.mem.endsWith(u8, text, "%")) return std.fmt.parseFloat(f32, text) catch null; const value = std.fmt.parseFloat(f32, text[0 .. text.len - 1]) catch return null; return value / 100.0;}fn clamp(value: f32) u8 { if (!(value > 0)) return 0; if (value >= 255) return 255; return @intFromFloat(@round(value));}fn fromHsl(hue: f32, saturation: f32, lightness: f32, opaque_alpha: u8) u32 { const s = std.math.clamp(saturation, 0, 1); const l = std.math.clamp(lightness, 0, 1); const chroma = (1.0 - @abs(2.0 * l - 1.0)) * s; const normalized = @mod(hue, 360.0) / 60.0; const second = chroma * (1.0 - @abs(@mod(normalized, 2.0) - 1.0)); const match = l - chroma / 2.0; const sector: u32 = @intFromFloat(@floor(normalized)); const triple: [3]f32 = switch (sector) { 0 => .{ chroma, second, 0 }, 1 => .{ second, chroma, 0 }, 2 => .{ 0, chroma, second }, 3 => .{ 0, second, chroma }, 4 => .{ second, 0, chroma }, else => .{ chroma, 0, second }, }; return pack( clamp((triple[0] + match) * 255.0), clamp((triple[1] + match) * 255.0), clamp((triple[2] + match) * 255.0), opaque_alpha, );}test "a named colour resolves case insensitively and an unknown name fails" { try std.testing.expectEqual(pack(255, 0, 0, 255), named("red").?); try std.testing.expectEqual(pack(255, 0, 0, 255), named("RED").?); try std.testing.expectEqual(pack(0x66, 0x33, 0x99, 255), named("rebeccapurple").?); try std.testing.expect(named("notacolour") == null); try std.testing.expect(named("") == null);}test "hex bodies expand from three, four, six, and eight digits" { try std.testing.expectEqual(pack(0xAA, 0xBB, 0xCC, 255), hex("abc").?); try std.testing.expectEqual(pack(0xAA, 0xBB, 0xCC, 0xDD), hex("abcd").?); try std.testing.expectEqual(pack(0x12, 0x34, 0x56, 255), hex("123456").?); try std.testing.expectEqual(pack(0x12, 0x34, 0x56, 0x78), hex("12345678").?); try std.testing.expect(hex("12345") == null); try std.testing.expect(hex("zzz") == null);}test "rgb and rgba take numbers, percentages, and an alpha" { try std.testing.expectEqual(pack(1, 2, 3, 255), function("rgb", "1, 2, 3").?); try std.testing.expectEqual(pack(255, 0, 0, 128), function("rgba", "255 0 0 / 0.502").?); try std.testing.expectEqual(pack(255, 128, 0, 255), function("rgb", "100%, 50%, 0%").?); try std.testing.expect(function("rgb", "1, 2") == null); try std.testing.expect(function("lab", "1, 2, 3") == null);}test "hsl converts hue, saturation, and lightness into channels" { try std.testing.expectEqual(pack(255, 0, 0, 255), function("hsl", "0, 100%, 50%").?); try std.testing.expectEqual(pack(0, 255, 0, 255), function("hsl", "120deg 100% 50%").?); try std.testing.expectEqual(pack(128, 128, 128, 255), function("hsl", "0, 0%, 50.2%").?);}test "channel packing and reading are inverse" { const packed_value = pack(18, 52, 86, 120); try std.testing.expectEqual(@as(u8, 18), red(packed_value)); try std.testing.expectEqual(@as(u8, 52), green(packed_value)); try std.testing.expectEqual(@as(u8, 86), blue(packed_value)); try std.testing.expectEqual(@as(u8, 120), alpha(packed_value)); try std.testing.expectEqual(@as(u32, 0), transparent);}Source: lib/css/src/value/root.zig:19
zig
pub const color = @import("color.zig");Complete call list for value.color.function
7 direct calls.
lib.css.src.value.color.channel[function] — private source atlib/css/src/value/color.zig:286in nearest public ownertiny.css.value.colorlib.css.src.value.color.fromHsl[function] — private source atlib/css/src/value/color.zig:316in nearest public ownertiny.css.value.colorlib.css.src.value.color.opacity[function] — private source atlib/css/src/value/color.zig:295in nearest public ownertiny.css.value.colortiny.css.value.color.pack[function] atlib/css/src/value/color.zig:10lib.css.src.value.color.ratio[function] — private source atlib/css/src/value/color.zig:304in nearest public ownertiny.css.value.colorlib.css.src.value.color.scalar[function] — private source atlib/css/src/value/color.zig:280in nearest public ownertiny.css.value.colorlib.css.src.value.color.split[function] — private source atlib/css/src/value/color.zig:269in nearest public ownertiny.css.value.color
Complete caller list for value.color.pack
13 direct callers.
lib.css.src.cascade.resolve.colored[function] — private source atlib/css/src/cascade/resolve.zig:411in nearest public ownerlib.css.src.cascade.resolvelib.css.src.cascade.test.colored[function] — private source atlib/css/src/cascade/test.zig:55in nearest public ownerlib.css.src.cascade.testlib.css.src.property.expand.test_background_takes_a_colour_or_an_image_and_rejects_both_at_once[function] — test source atlib/css/src/property/expand.zig:410in nearest public ownerlib.css.src.property.expandlib.css.src.property.expand.test_border_takes_its_three_components_in_any_order[function] — test source atlib/css/src/property/expand.zig:376in nearest public ownerlib.css.src.property.expandlib.css.src.value.color.fromHsl[function] — private source atlib/css/src/value/color.zig:316in nearest public ownertiny.css.value.colortiny.css.value.color.function[function] atlib/css/src/value/color.zig:233tiny.css.value.color.hex[function] atlib/css/src/value/color.zig:219lib.css.src.value.color.test_a_named_colour_resolves_case_insensitively_and_an_unknown_name_fails[function] — test source atlib/css/src/value/color.zig:340in nearest public ownertiny.css.value.colorlib.css.src.value.color.test_channel_packing_and_reading_are_inverse[function] — test source atlib/css/src/value/color.zig:371in nearest public ownertiny.css.value.colorlib.css.src.value.color.test_hex_bodies_expand_from_three,_four,_six,_and_eight_digits[function] — test source atlib/css/src/value/color.zig:348in nearest public ownertiny.css.value.colorlib.css.src.value.color.test_hsl_converts_hue,_saturation,_and_lightness_into_channels[function] — test source atlib/css/src/value/color.zig:365in nearest public ownertiny.css.value.colorlib.css.src.value.color.test_rgb_and_rgba_take_numbers,_percentages,_and_an_alpha[function] — test source atlib/css/src/value/color.zig:357in nearest public ownertiny.css.value.colorlib.css.src.value.parse.test_colours_arrive_as_names,_hashes,_and_functions[function] — test source atlib/css/src/value/parse.zig:319in nearest public ownerlib.css.src.value.parse
Audit
| Definitions | 12 |
|---|---|
| Public names | 12 |
| Members | 2 |
| Version | 26.7.0 |
| Revision | daab053ee433 |