// Color: 4 bytes (r, g, b, a)
///|
/// Color, 4 components, R8G8B8A8 (32bit).
pub struct Color {
r : Byte
g : Byte
b : Byte
a : Byte
} derive(Eq, Debug)
///|
/// Create a new Color from RGBA components.
pub fn Color::new(r : Int, g : Int, b : Int, a : Int) -> Color {
{ r: r.to_byte(), g: g.to_byte(), b: b.to_byte(), a: a.to_byte() }
}
///|
/// Serialize Color to bytes.
pub fn Color::to_bytes(color : Color) -> Bytes {
[color.r, color.g, color.b, color.a]
}
///|
/// Deserialize Color from bytes.
pub fn Color::from_bytes(b : Bytes) -> Color {
{ r: b[0], g: b[1], b: b[2], a: b[3] }
}
// Color constants
///|
/// Light gray color.
pub let lightgray : Color = { r: b'\xC8', g: b'\xC8', b: b'\xC8', a: b'\xFF' }
///|
/// Gray color.
pub let gray : Color = { r: b'\x82', g: b'\x82', b: b'\x82', a: b'\xFF' }
///|
/// Dark gray color.
pub let darkgray : Color = { r: b'\x50', g: b'\x50', b: b'\x50', a: b'\xFF' }
///|
/// Yellow color.
pub let yellow : Color = { r: b'\xFD', g: b'\xF9', b: b'\x00', a: b'\xFF' }
///|
/// Gold color.
pub let gold : Color = { r: b'\xFF', g: b'\xCB', b: b'\x00', a: b'\xFF' }
///|
/// Orange color.
pub let orange : Color = { r: b'\xFF', g: b'\xA1', b: b'\x00', a: b'\xFF' }
///|
/// Pink color.
pub let pink : Color = { r: b'\xFF', g: b'\x6D', b: b'\xC2', a: b'\xFF' }
///|
/// Red color.
pub let red : Color = { r: b'\xE6', g: b'\x29', b: b'\x37', a: b'\xFF' }
///|
/// Maroon color.
pub let maroon : Color = { r: b'\xBE', g: b'\x21', b: b'\x37', a: b'\xFF' }
///|
/// Green color.
pub let green : Color = { r: b'\x00', g: b'\xE4', b: b'\x30', a: b'\xFF' }
///|
/// Lime color.
pub let lime : Color = { r: b'\x00', g: b'\x9E', b: b'\x2F', a: b'\xFF' }
///|
/// Dark green color.
pub let darkgreen : Color = { r: b'\x00', g: b'\x75', b: b'\x2C', a: b'\xFF' }
///|
/// Sky blue color.
pub let skyblue : Color = { r: b'\x66', g: b'\xBF', b: b'\xFF', a: b'\xFF' }
///|
/// Blue color.
pub let blue : Color = { r: b'\x00', g: b'\x79', b: b'\xF1', a: b'\xFF' }
///|
/// Dark blue color.
pub let darkblue : Color = { r: b'\x00', g: b'\x52', b: b'\xAC', a: b'\xFF' }
///|
/// Purple color.
pub let purple : Color = { r: b'\xC8', g: b'\x7A', b: b'\xFF', a: b'\xFF' }
///|
/// Violet color.
pub let violet : Color = { r: b'\x87', g: b'\x3C', b: b'\xBE', a: b'\xFF' }
///|
/// Dark purple color.
pub let darkpurple : Color = { r: b'\x70', g: b'\x1F', b: b'\x7E', a: b'\xFF' }
///|
/// Beige color.
pub let beige : Color = { r: b'\xD3', g: b'\xB0', b: b'\x83', a: b'\xFF' }
///|
/// Brown color.
pub let brown : Color = { r: b'\x7F', g: b'\x6A', b: b'\x4F', a: b'\xFF' }
///|
/// Dark brown color.
pub let darkbrown : Color = { r: b'\x4C', g: b'\x3F', b: b'\x2F', a: b'\xFF' }
///|
/// White color.
pub let white : Color = { r: b'\xFF', g: b'\xFF', b: b'\xFF', a: b'\xFF' }
///|
/// Black color.
pub let black : Color = { r: b'\x00', g: b'\x00', b: b'\x00', a: b'\xFF' }
///|
/// Blank color (fully transparent).
pub let blank : Color = { r: b'\x00', g: b'\x00', b: b'\x00', a: b'\x00' }
///|
/// Magenta color.
pub let magenta : Color = { r: b'\xFF', g: b'\x00', b: b'\xFF', a: b'\xFF' }
///|
/// Raylib white color (off-white).
pub let raywhite : Color = { r: b'\xF5', g: b'\xF5', b: b'\xF5', a: b'\xFF' }
// Color utility wrappers
///|
/// Get color with alpha applied, alpha goes from 0.0 to 1.0.
pub fn fade(color : Color, alpha : Float) -> Color {
let a : Float = if alpha < 0.0 {
0.0
} else if alpha > 1.0 {
1.0
} else {
alpha
}
let alpha_byte : Float = 255.0 * a
{ ..color, a: alpha_byte.to_int().to_byte() }
}
///|
/// Get color with alpha applied, alpha goes from 0.0 to 1.0.
pub fn color_alpha(color : Color, alpha : Float) -> Color {
fade(color, alpha)
}
///|
/// Get hexadecimal value for a Color (0xRRGGBBAA).
pub fn color_to_int(color : Color) -> Int {
(color.r.to_int() << 24) |
(color.g.to_int() << 16) |
(color.b.to_int() << 8) |
color.a.to_int()
}
///|
/// Get Color structure from hexadecimal value.
pub fn get_color(hex_value : Int) -> Color {
{
r: ((hex_value >> 24) & 0xFF).to_byte(),
g: ((hex_value >> 16) & 0xFF).to_byte(),
b: ((hex_value >> 8) & 0xFF).to_byte(),
a: (hex_value & 0xFF).to_byte(),
}
}
///|
/// Get a Color from HSV values, hue [0..360], saturation/value [0..1].
pub fn color_from_hsv(hue : Float, saturation : Float, value : Float) -> Color {
let h60 : Float = hue / 60.0
let six : Float = 6.0
// Red channel
let kr : Float = fmodf(5.0 + h60, six)
let tr : Float = 4.0 - kr
let kr : Float = if tr < kr { tr } else { kr }
let kr : Float = if kr < 1.0 { kr } else { 1.0 }
let kr : Float = if kr > 0.0 { kr } else { 0.0 }
let r = ((value - value * saturation * kr) * 255.0).to_int()
// Green channel
let kg : Float = fmodf(3.0 + h60, six)
let tg : Float = 4.0 - kg
let kg : Float = if tg < kg { tg } else { kg }
let kg : Float = if kg < 1.0 { kg } else { 1.0 }
let kg : Float = if kg > 0.0 { kg } else { 0.0 }
let g = ((value - value * saturation * kg) * 255.0).to_int()
// Blue channel
let kb : Float = fmodf(1.0 + h60, six)
let tb : Float = 4.0 - kb
let kb : Float = if tb < kb { tb } else { kb }
let kb : Float = if kb < 1.0 { kb } else { 1.0 }
let kb : Float = if kb > 0.0 { kb } else { 0.0 }
let b = ((value - value * saturation * kb) * 255.0).to_int()
{ r: r.to_byte(), g: g.to_byte(), b: b.to_byte(), a: b'\xFF' }
}
///|
/// Get color multiplied with another color.
pub fn color_tint(color : Color, tint : Color) -> Color {
{
r: (color.r.to_int() * tint.r.to_int() / 255).to_byte(),
g: (color.g.to_int() * tint.g.to_int() / 255).to_byte(),
b: (color.b.to_int() * tint.b.to_int() / 255).to_byte(),
a: (color.a.to_int() * tint.a.to_int() / 255).to_byte(),
}
}
///|
/// Get color with brightness correction, brightness factor goes from -1.0 to 1.0.
pub fn color_brightness(color : Color, factor : Float) -> Color {
let factor : Float = if factor > 1.0 {
1.0
} else if factor < -1.0 {
-1.0
} else {
factor
}
let r = Float::from_int(color.r.to_int())
let g = Float::from_int(color.g.to_int())
let b = Float::from_int(color.b.to_int())
let (r, g, b) : (Float, Float, Float) = if factor < 0.0 {
let f : Float = 1.0 + factor
(r * f, g * f, b * f)
} else {
(
(255.0 - r) * factor + r,
(255.0 - g) * factor + g,
(255.0 - b) * factor + b,
)
}
{
r: r.to_int().to_byte(),
g: g.to_int().to_byte(),
b: b.to_int().to_byte(),
a: color.a,
}
}
///|
/// Get color lerp interpolation between two colors, factor [0.0..1.0].
pub fn color_lerp(color1 : Color, color2 : Color, factor : Float) -> Color {
let f : Float = if factor < 0.0 {
0.0
} else if factor > 1.0 {
1.0
} else {
factor
}
let inv : Float = 1.0 - f
{
r: (inv * Float::from_int(color1.r.to_int()) +
f * Float::from_int(color2.r.to_int()))
.to_int()
.to_byte(),
g: (inv * Float::from_int(color1.g.to_int()) +
f * Float::from_int(color2.g.to_int()))
.to_int()
.to_byte(),
b: (inv * Float::from_int(color1.b.to_int()) +
f * Float::from_int(color2.b.to_int()))
.to_int()
.to_byte(),
a: (inv * Float::from_int(color1.a.to_int()) +
f * Float::from_int(color2.a.to_int()))
.to_int()
.to_byte(),
}
}
///|
/// Check if two colors are equal.
pub fn color_is_equal(col1 : Color, col2 : Color) -> Bool {
col1 == col2
}
///|
/// Get Color normalized as float [0..1].
pub fn color_normalize(color : Color) -> Vector4 {
{
x: Float::from_int(color.r.to_int()) / 255.0,
y: Float::from_int(color.g.to_int()) / 255.0,
z: Float::from_int(color.b.to_int()) / 255.0,
w: Float::from_int(color.a.to_int()) / 255.0,
}
}
///|
/// Get Color from normalized values [0..1].
pub fn color_from_normalized(normalized : Vector4) -> Color {
{
r: (normalized.x * 255.0).to_int().to_byte(),
g: (normalized.y * 255.0).to_int().to_byte(),
b: (normalized.z * 255.0).to_int().to_byte(),
a: (normalized.w * 255.0).to_int().to_byte(),
}
}
///|
/// Get HSV values for a Color, hue [0..360], saturation/value [0..1].
pub fn color_to_hsv(color : Color) -> Vector3 {
let rf = Float::from_int(color.r.to_int()) / 255.0
let gf = Float::from_int(color.g.to_int()) / 255.0
let bf = Float::from_int(color.b.to_int()) / 255.0
let min = fminf(fminf(rf, gf), bf)
let max = fmaxf(fmaxf(rf, gf), bf)
let v = max
let delta = max - min
if delta < 0.00001 {
return { x: 0.0, y: 0.0, z: v }
}
let s = if max > 0.0 { delta / max } else { return { x: 0.0, y: 0.0, z: v } }
let h = if rf >= max {
(gf - bf) / delta
} else if gf >= max {
2.0 + (bf - rf) / delta
} else {
4.0 + (rf - gf) / delta
}
let h = h * 60.0
let h = if h < 0.0 { h + 360.0 } else { h }
{ x: h, y: s, z: v }
}
///|
/// Get color with contrast correction, contrast values between -1.0 and 1.0.
pub fn color_contrast(color : Color, contrast : Float) -> Color {
let contrast : Float = if contrast < -1.0 {
-1.0
} else if contrast > 1.0 {
1.0
} else {
contrast
}
let factor : Float = (1.0 + contrast) * (1.0 + contrast)
let clampf = fn(v : Float) -> Float {
if v < 0.0 {
return 0.0
}
if v > 255.0 {
return 255.0
}
v
}
let pr : Float = Float::from_int(color.r.to_int()) / 255.0
let pr : Float = clampf(((pr - 0.5) * factor + 0.5) * 255.0)
let pg : Float = Float::from_int(color.g.to_int()) / 255.0
let pg : Float = clampf(((pg - 0.5) * factor + 0.5) * 255.0)
let pb : Float = Float::from_int(color.b.to_int()) / 255.0
let pb : Float = clampf(((pb - 0.5) * factor + 0.5) * 255.0)
{
r: pr.to_int().to_byte(),
g: pg.to_int().to_byte(),
b: pb.to_int().to_byte(),
a: color.a,
}
}
///|
/// Get src alpha-blended into dst color with tint.
pub fn color_alpha_blend(dst : Color, src : Color, tint : Color) -> Color {
// Apply tint to source
let sr = (src.r.to_int() * (tint.r.to_int() + 1)) >> 8
let sg = (src.g.to_int() * (tint.g.to_int() + 1)) >> 8
let sb = (src.b.to_int() * (tint.b.to_int() + 1)) >> 8
let sa = (src.a.to_int() * (tint.a.to_int() + 1)) >> 8
if sa == 0 {
dst
} else if sa == 255 {
{ r: sr.to_byte(), g: sg.to_byte(), b: sb.to_byte(), a: sa.to_byte() }
} else {
let alpha = sa + 1
let out_a = (alpha * 256 + dst.a.to_int() * (256 - alpha)) >> 8
if out_a > 0 {
let out_r = (
(sr * alpha * 256 + dst.r.to_int() * dst.a.to_int() * (256 - alpha)) /
out_a
) >>
8
let out_g = (
(sg * alpha * 256 + dst.g.to_int() * dst.a.to_int() * (256 - alpha)) /
out_a
) >>
8
let out_b = (
(sb * alpha * 256 + dst.b.to_int() * dst.a.to_int() * (256 - alpha)) /
out_a
) >>
8
{
r: out_r.to_byte(),
g: out_g.to_byte(),
b: out_b.to_byte(),
a: out_a.to_byte(),
}
} else {
{ r: b'\x00', g: b'\x00', b: b'\x00', a: b'\x00' }
}
}
}
///|
pub using @ffi {get_pixel_data_size}