authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2024-12-29 01:48:15 -08:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2024-12-29 01:48:15 -08:00
log8c09516944357d85f4ffa3d7a1421f96f63ac420
treec7c8525ea3bf15b99f208cb2aba986b8d86d67f6
parentb9313635237c1f05ed4e40b8b1dba5a51f76ef0f

add test


8 files changed, 87 insertions(+), 11 deletions(-)

CMYK.zig+10
...@@ -27,3 +27,13 @@ pub fn initCMYKA(c: f32, m: f32, y: f32, k: f32, a: f32) Self {...@@ -27,3 +27,13 @@ pub fn initCMYKA(c: f32, m: f32, y: f32, k: f32, a: f32) Self {
27pub fn eql(x: Self, y: Self) bool {27pub fn eql(x: Self, y: Self) bool {
28 return x.c == y.c and x.m == y.m and x.y == y.y and x.k == y.k and x.a == y.a;28 return x.c == y.c and x.m == y.m and x.y == y.y and x.k == y.k and x.a == y.a;
29}29}
30
31pub fn to_array(x: Self) [5]f32 {
32 return .{
33 x.c,
34 x.m,
35 x.y,
36 x.k,
37 x.a,
38 };
39}
HSL.zig+3
...@@ -2,6 +2,7 @@...@@ -2,6 +2,7 @@
22
3const std = @import("std");3const std = @import("std");
4const Self = @This();4const Self = @This();
5const _x = @import("./_x.zig");
56
6h: f32, // hue7h: f32, // hue
7s: f32, // saturation8s: f32, // saturation
...@@ -24,3 +25,5 @@ pub fn initHSLA(h: f32, s: f32, l: f32, a: f32) Self {...@@ -24,3 +25,5 @@ pub fn initHSLA(h: f32, s: f32, l: f32, a: f32) Self {
24pub fn eql(x: Self, y: Self) bool {25pub fn eql(x: Self, y: Self) bool {
25 return x.h == y.h and x.s == y.s and x.l == y.l and x.a == y.a;26 return x.h == y.h and x.s == y.s and x.l == y.l and x.a == y.a;
26}27}
28
29pub usingnamespace _x.mixin(@This(), f32, .h, .s, .l);
HSV.zig+3
...@@ -2,6 +2,7 @@...@@ -2,6 +2,7 @@
22
3const std = @import("std");3const std = @import("std");
4const Self = @This();4const Self = @This();
5const _x = @import("./_x.zig");
56
6h: f32, // hue7h: f32, // hue
7s: f32, // saturation8s: f32, // saturation
...@@ -24,3 +25,5 @@ pub fn initHSVA(h: f32, s: f32, v: f32, a: f32) Self {...@@ -24,3 +25,5 @@ pub fn initHSVA(h: f32, s: f32, v: f32, a: f32) Self {
24pub fn eql(x: Self, y: Self) bool {25pub fn eql(x: Self, y: Self) bool {
25 return x.h == y.h and x.s == y.s and x.v == y.v and x.a == y.a;26 return x.h == y.h and x.s == y.s and x.v == y.v and x.a == y.a;
26}27}
28
29pub usingnamespace _x.mixin(@This(), f32, .h, .s, .v);
LinearRgb.zig+3
...@@ -2,6 +2,7 @@...@@ -2,6 +2,7 @@
22
3const std = @import("std");3const std = @import("std");
4const Self = @This();4const Self = @This();
5const _x = @import("./_x.zig");
56
6r: f32, // red7r: f32, // red
7g: f32, // green8g: f32, // green
...@@ -28,3 +29,5 @@ pub fn eql(x: Self, y: Self) bool {...@@ -28,3 +29,5 @@ pub fn eql(x: Self, y: Self) bool {
28pub fn relative_luminance(x: Self) f32 {29pub fn relative_luminance(x: Self) f32 {
29 return (0.2126 * x.r) + (0.7152 * x.g) + (0.0722 * x.b);30 return (0.2126 * x.r) + (0.7152 * x.g) + (0.0722 * x.b);
30}31}
32
33pub usingnamespace _x.mixin(@This(), f32, .r, .g, .b);
_x.zig+2-1
...@@ -2,6 +2,7 @@ const std = @import("std");...@@ -2,6 +2,7 @@ const std = @import("std");
22
3pub fn mixin(3pub fn mixin(
4 comptime T: type,4 comptime T: type,
5 comptime I: type,
5 comptime f1: std.meta.FieldEnum(T),6 comptime f1: std.meta.FieldEnum(T),
6 comptime f2: std.meta.FieldEnum(T),7 comptime f2: std.meta.FieldEnum(T),
7 comptime f3: std.meta.FieldEnum(T),8 comptime f3: std.meta.FieldEnum(T),
...@@ -25,7 +26,7 @@ pub fn mixin(...@@ -25,7 +26,7 @@ pub fn mixin(
25 return x;26 return x;
26 }27 }
2728
28 pub fn to_array(x: T, comptime I: type) [4]I {29 pub fn to_array(x: T) [4]I {
29 return .{30 return .{
30 @field(x, @tagName(f1)),31 @field(x, @tagName(f1)),
31 @field(x, @tagName(f2)),32 @field(x, @tagName(f2)),
build.zig+11-2
...@@ -25,6 +25,15 @@ pub fn build(b: *std.Build) void {...@@ -25,6 +25,15 @@ pub fn build(b: *std.Build) void {
25 const run_step = b.step("run", "Run the app");25 const run_step = b.step("run", "Run the app");
26 run_step.dependOn(&run_cmd.step);26 run_step.dependOn(&run_cmd.step);
2727
28 const test_step = b.step("test", "dummy test step to pass CI checks");28 const tests = b.addTest(.{
29 _ = test_step;29 .root_source_file = b.path("test.zig"),
30 .target = target,
31 .optimize = mode,
32 });
33 deps.addAllTo(tests);
34
35 const test_step = b.step("test", "Run all library tests");
36 const tests_run = b.addRunArtifact(tests);
37 tests_run.has_side_effects = true;
38 test_step.dependOn(&tests_run.step);
30}39}
sRGB.zig+8-8
...@@ -73,7 +73,7 @@ pub fn format(x: Self, comptime fmt: []const u8, options: std.fmt.FormatOptions,...@@ -73,7 +73,7 @@ pub fn format(x: Self, comptime fmt: []const u8, options: std.fmt.FormatOptions,
73 });73 });
74}74}
7575
76pub usingnamespace _x.mixin(@This(), .r, .g, .b);76pub usingnamespace _x.mixin(@This(), u8, .r, .g, .b);
7777
78pub fn to_linear_rgb(x: Self) color.LinearRgb {78pub fn to_linear_rgb(x: Self) color.LinearRgb {
79 const lut = comptime blk: {79 const lut = comptime blk: {
...@@ -94,7 +94,7 @@ pub fn to_linear_rgb(x: Self) color.LinearRgb {...@@ -94,7 +94,7 @@ pub fn to_linear_rgb(x: Self) color.LinearRgb {
94}94}
9595
96pub fn to_float(x: Self) Float {96pub fn to_float(x: Self) Float {
97 return Self{97 return .{
98 .r = @as(f32, @floatFromInt(x.r)) / 255.0,98 .r = @as(f32, @floatFromInt(x.r)) / 255.0,
99 .g = @as(f32, @floatFromInt(x.g)) / 255.0,99 .g = @as(f32, @floatFromInt(x.g)) / 255.0,
100 .b = @as(f32, @floatFromInt(x.b)) / 255.0,100 .b = @as(f32, @floatFromInt(x.b)) / 255.0,
...@@ -119,9 +119,9 @@ pub fn to_hsl(x: Self) color.HSL {...@@ -119,9 +119,9 @@ pub fn to_hsl(x: Self) color.HSL {
119 const delta = cmax - cmin;119 const delta = cmax - cmin;
120 const h = blk: {120 const h = blk: {
121 if (delta == 0) break :blk 0;121 if (delta == 0) break :blk 0;
122 if (cmax == f.r) break :blk ((((f.g - f.b) / delta) % 6) * 60) % 360;122 if (cmax == f.r) break :blk @rem(((f.g - f.b) / delta), 6.0) / 6.0;
123 if (cmax == f.g) break :blk ((((f.b - f.r) / delta) + 2) * 60) % 360;123 if (cmax == f.g) break :blk (((f.b - f.r) / delta) + 2) / 6.0;
124 if (cmax == f.b) break :blk ((((f.r - f.g) / delta) + 4) * 60) % 360;124 if (cmax == f.b) break :blk (((f.r - f.g) / delta) + 4) / 6.0;
125 unreachable;125 unreachable;
126 };126 };
127 const l = (cmax + cmin) / 2;127 const l = (cmax + cmin) / 2;
...@@ -137,9 +137,9 @@ pub fn to_hsv(x: Self) color.HSV {...@@ -137,9 +137,9 @@ pub fn to_hsv(x: Self) color.HSV {
137 const delta = cmax - cmin;137 const delta = cmax - cmin;
138 const h = blk: {138 const h = blk: {
139 if (delta == 0) break :blk 0;139 if (delta == 0) break :blk 0;
140 if (cmax == f.r) break :blk ((((f.g - f.b) / delta) % 6) * 60) % 360;140 if (cmax == f.r) break :blk (@rem(((f.g - f.b) / delta), 6.0) / 6.0);
141 if (cmax == f.g) break :blk ((((f.b - f.r) / delta) + 2) * 60) % 360;141 if (cmax == f.g) break :blk ((((f.b - f.r) / delta) + 2) / 6.0);
142 if (cmax == f.b) break :blk ((((f.r - f.g) / delta) + 4) * 60) % 360;142 if (cmax == f.b) break :blk ((((f.r - f.g) / delta) + 4) / 6.0);
143 unreachable;143 unreachable;
144 };144 };
145 const s = if (cmax == 0) 0 else delta / cmax;145 const s = if (cmax == 0) 0 else delta / cmax;
test.zig created+47
...@@ -0,0 +1,47 @@
1const std = @import("std");
2const color = @import("color");
3
4test {
5 // https://www.colorhexa.com/4fc3f7
6 const o = color.sRGB.parseHexConst("#4FC3F7");
7 {
8 const r, const g, const b, const a = o.to_array();
9 try std.testing.expect(r == 79);
10 try std.testing.expect(g == 195);
11 try std.testing.expect(b == 247);
12 try std.testing.expect(a == 255);
13 }
14 {
15 // 68% cyan, 21.1% magenta, 0% yellow and 3.1% black
16 const c, const m, const y, const k, const a = o.to_cmyk().to_array();
17 try std.testing.expectApproxEqAbs(0.68, c, 0.01);
18 try std.testing.expectApproxEqAbs(0.21, m, 0.01);
19 try std.testing.expectApproxEqAbs(0.00, y, 0.01);
20 try std.testing.expectApproxEqAbs(0.03, k, 0.01);
21 try std.testing.expect(a == 1.0);
22 }
23 {
24 // 198.6°, 91.3, 63.9
25 const h, const s, const l, const a = o.to_hsl().to_array();
26 try std.testing.expectApproxEqAbs(0.552, h, 0.001);
27 try std.testing.expectApproxEqAbs(0.913, s, 0.001);
28 try std.testing.expectApproxEqAbs(0.639, l, 0.001);
29 try std.testing.expect(a == 1.0);
30 }
31 {
32 // 198.6°, 68, 96.9
33 const h, const s, const v, const a = o.to_hsv().to_array();
34 try std.testing.expectApproxEqAbs(0.552, h, 0.001);
35 try std.testing.expectApproxEqAbs(0.680, s, 0.001);
36 try std.testing.expectApproxEqAbs(0.969, v, 0.001);
37 try std.testing.expect(a == 1.0);
38 }
39 {
40 // 0.0781874218051863, 0.545724461370187, 0.930110858375424
41 const r, const g, const b, const a = o.to_linear_rgb().to_array();
42 try std.testing.expectApproxEqAbs(0.078, r, 0.001);
43 try std.testing.expectApproxEqAbs(0.545, g, 0.001);
44 try std.testing.expectApproxEqAbs(0.930, b, 0.001);
45 try std.testing.expect(a == 1.0);
46 }
47}