aboutsummaryrefslogtreecommitdiff
path: root/src/sfml/graphics/color.zig
diff options
context:
space:
mode:
authortslil clingman <>2021-09-01 12:59:50 -0400
committertslil clingman <>2021-09-01 12:59:50 -0400
commit6a2d132873ce7b40405a3dc000a12539fffd969b (patch)
tree3b730360b348900fbc937bd44b89c293c39ca00c /src/sfml/graphics/color.zig
Init
Diffstat (limited to 'src/sfml/graphics/color.zig')
-rw-r--r--src/sfml/graphics/color.zig166
1 files changed, 166 insertions, 0 deletions
diff --git a/src/sfml/graphics/color.zig b/src/sfml/graphics/color.zig
new file mode 100644
index 0000000..d6aa850
--- /dev/null
+++ b/src/sfml/graphics/color.zig
@@ -0,0 +1,166 @@
+//! Utility class for manipulating RGBA colors.
+
+const sf = @import("../sfml_import.zig");
+const math = @import("std").math;
+
+pub const Color = packed struct {
+ /// Converts a color from a csfml object
+ /// For inner workings
+ pub fn fromCSFML(col: sf.c.sfColor) Color {
+ return @bitCast(Color, col);
+ }
+
+ /// Converts this color to a csfml one
+ /// For inner workings
+ pub fn toCSFML(self: Color) sf.c.sfColor {
+ return @bitCast(sf.c.sfColor, self);
+ }
+
+ /// Inits a color with rgb components
+ pub fn fromRGB(red: u8, green: u8, blue: u8) Color {
+ return Color{
+ .r = red,
+ .g = green,
+ .b = blue,
+ .a = 0xff,
+ };
+ }
+
+ /// Inits a color with rgba components
+ pub fn fromRGBA(red: u8, green: u8, blue: u8, alpha: u8) Color {
+ return Color{
+ .r = red,
+ .g = green,
+ .b = blue,
+ .a = alpha,
+ };
+ }
+
+ /// Inits a color from a 32bits value (RGBA in that order)
+ pub fn fromInteger(int: u32) Color {
+ return Color{
+ .r = @truncate(u8, (int & 0xff000000) >> 24),
+ .g = @truncate(u8, (int & 0x00ff0000) >> 16),
+ .b = @truncate(u8, (int & 0x0000ff00) >> 8),
+ .a = @truncate(u8, (int & 0x000000ff) >> 0),
+ };
+ }
+
+ /// Gets a 32 bit integer representing the color
+ pub fn toInteger(self: Color) u32 {
+ return (@intCast(u32, self.r) << 24) |
+ (@intCast(u32, self.g) << 16) |
+ (@intCast(u32, self.b) << 8) |
+ (@intCast(u32, self.a) << 0);
+ }
+
+ /// Creates a color with rgba floats from 0 to 1
+ fn fromFloats(red: f32, green: f32, blue: f32, alpha: f32) Color {
+ return Color{
+ .r = @floatToInt(u8, math.clamp(red, 0.0, 1.0) * 255.0),
+ .g = @floatToInt(u8, math.clamp(green, 0.0, 1.0) * 255.0),
+ .b = @floatToInt(u8, math.clamp(blue, 0.0, 1.0) * 255.0),
+ .a = @floatToInt(u8, math.clamp(alpha, 0.0, 1.0) * 255.0),
+ };
+ }
+
+ /// Creates a color from HSV and transparency components (this is not part of the SFML)
+ /// hue is in degrees, saturation and value are in percents
+ pub fn fromHSVA(hue: f32, saturation: f32, value: f32, alpha: f32) Color {
+ const h = hue;
+ const s = saturation / 100;
+ const v = value / 100;
+ const a = alpha;
+
+ var hh: f32 = h;
+
+ if (v <= 0.0)
+ return fromFloats(0, 0, 0, a);
+
+ if (hh >= 360.0)
+ hh = 0;
+ hh /= 60.0;
+
+ var ff: f32 = hh - math.floor(hh);
+
+ var p: f32 = v * (1.0 - s);
+ var q: f32 = v * (1.0 - (s * ff));
+ var t: f32 = v * (1.0 - (s * (1.0 - ff)));
+
+ return switch (@floatToInt(usize, hh)) {
+ 0 => fromFloats(v, t, p, a),
+ 1 => fromFloats(q, v, p, a),
+ 2 => fromFloats(p, v, t, a),
+ 3 => fromFloats(p, q, v, a),
+ 4 => fromFloats(t, p, v, a),
+ else => fromFloats(v, p, q, a),
+ };
+ }
+
+ // Colors
+ /// Black color
+ pub const Black = Color.fromRGB(0, 0, 0);
+ /// White color
+ pub const White = Color.fromRGB(255, 255, 255);
+ /// Red color
+ pub const Red = Color.fromRGB(255, 0, 0);
+ /// Green color
+ pub const Green = Color.fromRGB(0, 255, 0);
+ /// Blue color
+ pub const Blue = Color.fromRGB(0, 0, 255);
+ /// Yellow color
+ pub const Yellow = Color.fromRGB(255, 255, 0);
+ /// Magenta color
+ pub const Magenta = Color.fromRGB(255, 0, 255);
+ /// Cyan color
+ pub const Cyan = Color.fromRGB(0, 255, 255);
+ /// Transparent color
+ pub const Transparent = Color.fromRGBA(0, 0, 0, 0);
+
+ /// Red component
+ r: u8,
+ /// Green component
+ g: u8,
+ /// Blue component
+ b: u8,
+ /// Alpha (opacity) component
+ a: u8,
+};
+
+test "color: conversions" {
+ const tst = @import("std").testing;
+
+ var code: u32 = 0x4BDA9CFF;
+ var col = Color.fromInteger(code);
+
+ try tst.expectEqual(Color.fromRGB(75, 218, 156), col);
+ try tst.expectEqual(code, col.toInteger());
+
+ var csfml_col = sf.c.sfColor_fromInteger(@as(c_uint, code));
+
+ try tst.expectEqual(Color.fromCSFML(csfml_col), col);
+}
+
+test "color: hsv to rgb" {
+ const tst = @import("std").testing;
+
+ var col = Color.fromHSVA(10, 20, 100, 255);
+
+ try tst.expectEqual(Color.fromRGB(255, 212, 204), col);
+}
+
+test "color: sane from/to CSFML color" {
+ const tst = @import("std").testing;
+
+ const col = Color.fromRGBA(5, 12, 28, 127);
+ const ccol = col.toCSFML();
+
+ try tst.expectEqual(col.r, ccol.r);
+ try tst.expectEqual(col.g, ccol.g);
+ try tst.expectEqual(col.b, ccol.b);
+ try tst.expectEqual(col.a, ccol.a);
+
+ const col2 = Color.fromCSFML(ccol);
+
+ try tst.expectEqual(col, col2);
+}