85 lines
2.0 KiB
Lua
85 lines
2.0 KiB
Lua
local hsluv = require("kanso.lib.hsluv")
|
|
|
|
---@class HSLuvColor
|
|
local Color = {}
|
|
local Color_mt = {
|
|
__index = Color,
|
|
__tostring = function(self)
|
|
return self:to_hex()
|
|
end,
|
|
}
|
|
|
|
local function none_to_hex()
|
|
return "NONE"
|
|
end
|
|
|
|
---Create a new HSLuv color object from a RGB hex string
|
|
---@param hex string Hex color
|
|
---@return HSLuvColor
|
|
function Color.new(hex)
|
|
if hex:lower() == "none" then
|
|
return setmetatable({ H = 0, S = 0, L = 0, to_hex = none_to_hex }, Color_mt)
|
|
end
|
|
local H, S, L = unpack(hsluv.hex_to_hsluv(hex))
|
|
return setmetatable({ H = H, S = S, L = L }, Color_mt)
|
|
end
|
|
|
|
function Color:to_rgb()
|
|
return hsluv.hsluv_to_rgb({ self.H, self.S, self.L })
|
|
end
|
|
|
|
function Color:to_hex()
|
|
return hsluv.hsluv_to_hex({ self.H, self.S, self.L })
|
|
end
|
|
|
|
local function blendRGB(a, b, r)
|
|
local c = {}
|
|
for i = 1, 3 do
|
|
c[i] = math.sqrt((1 - r) * math.pow(a[i], 2) + r * math.pow(b[i], 2))
|
|
end
|
|
return c
|
|
end
|
|
|
|
--- Blend Color with another color (hex)
|
|
---@param b string Hex color
|
|
---@param r number Blend ratio [0, 1]
|
|
---@return HSLuvColor
|
|
function Color:blend(b, r)
|
|
if b:lower() == "none" then
|
|
return self
|
|
end
|
|
local c = blendRGB(self:to_rgb(), hsluv.hex_to_rgb(b), r)
|
|
self.H, self.S, self.L = unpack(hsluv.rgb_to_hsluv(c))
|
|
return self
|
|
end
|
|
|
|
---@param r number Brighten ratio [-1, 1]
|
|
---@param bg? string background color, if light, r = -r
|
|
---@return HSLuvColor
|
|
function Color:brighten(r, bg)
|
|
if bg and bg:lower() == "none" then
|
|
return self
|
|
end
|
|
local bg_lightness = bg and hsluv.hex_to_hsluv(bg)[3] or 0
|
|
r = bg_lightness > 50 and -r or r
|
|
|
|
local lspace = r > 0 and 100 - self.L or self.L
|
|
self.L = self.L + lspace * r
|
|
return self
|
|
end
|
|
|
|
---@param r number Saturate ratio [-1, 1]
|
|
---@return HSLuvColor
|
|
function Color:saturate(r)
|
|
local lspace = r > 0 and 100 - self.S or self.S
|
|
self.S = self.S + lspace * r
|
|
return self
|
|
end
|
|
|
|
local M = {}
|
|
return setmetatable(M, {
|
|
__call = function(_, ...)
|
|
return Color.new(...)
|
|
end,
|
|
})
|