import SDL2 import HSLuv public struct Colour: Equatable { let r, g, b, a: Float } public extension Colour { static var zero: Self { .init(r: 0, g: 0, b: 0, a: 0) } static var black: Self { .init(r: 0, g: 0, b: 0, a: 1) } static var white: Self { .init(r: 1, g: 1, b: 1, a: 1) } init(r: Float, g: Float, b: Float) { self.init(r: r, g: g, b: b, a: 1.0) } init(fromSdl: SDL_Color) { self.init( r: Float(fromSdl.r) / 0xFF, g: Float(fromSdl.g) / 0xFF, b: Float(fromSdl.b) / 0xFF, a: Float(fromSdl.a) / 0xFF) } init(fromRgb24: UInt32) { self.init( r: Float((fromRgb24 >> 16) & 0xFF) / 0xFF, g: Float((fromRgb24 >> 8) & 0xFF) / 0xFF, b: Float((fromRgb24 >> 0) & 0xFF) / 0xFF, a: 1) } init(fromRgba32: UInt32) { self.init( r: Float((fromRgba32 >> 24) & 0xFF) / 0xFF, g: Float((fromRgba32 >> 16) & 0xFF) / 0xFF, b: Float((fromRgba32 >> 8) & 0xFF) / 0xFF, a: Float((fromRgba32 >> 0) & 0xFF) / 0xFF) } init(grey v: Float) { self.init(r: v, g: v, b: v) } func mix(with rhs: Colour, _ amount: Float) -> Colour { let x = amount.saturate return Colour( r: Float.lerp(r, rhs.r, x), g: Float.lerp(g, rhs.g, x), b: Float.lerp(b, rhs.b, x), a: Float.lerp(a, rhs.a, x)) } func lighten(by: Double) -> Colour { var hue = CGFloat(), sat = CGFloat(), light = CGFloat() rgbToHsluv(CGFloat(r), CGFloat(g), CGFloat(b), &hue, &sat, &light) let gamma: CGFloat = 3.0 light = pow((pow(light / 100, 1 / gamma) + CGFloat(by) * 0.8).saturate, gamma) * 100 var newR = CGFloat(), newG = CGFloat(), newB = CGFloat() hsluvToRgb(hue, sat, light, &newR, &newG, &newB) return Colour(r: Float(newR), g: Float(newG), b: Float(newB), a: a) } var linear: Colour { get { Colour( r: linearFromSrgb(r), g: linearFromSrgb(g), b: linearFromSrgb(b), a: a) } } func setAlpha(_ newAlpha: Float) -> Colour { return Colour(r: r, g: g, b: b, a: newAlpha) } } @inline(__always) fileprivate func srgbFromLinear(_ x: Float) -> Float { return (x < 0.0031308) ? x * 12.92 : 1.055 * pow(x, 1.0 / 2.4) - 0.055 } @inline(__always) fileprivate func linearFromSrgb(_ x: Float) -> Float { return (x < 0.04045) ? x / 12.92 : pow((x + 0.055) / 1.055, 2.4) }