kolorwheel 1.1.1

Color palette generator for GUI applications
Documentation
use std::convert::From;
use crate::hsl_color::HslColor;
use crate::rgb_color::RgbColor;

impl From<HslColor> for RgbColor {
    fn from(val: HslColor) -> Self {
        val.convert_hsl_to_rgb()
    }
}

impl HslColor {

    fn convert_hsl_to_rgb(&self) -> RgbColor {
        
        let h = self.h / 360.0;
        let s = self.s / 100.0;
        let l = self.l / 100.0;

        if s < 0.001 {
            let gray = (l * 255.0) as u8;
            return RgbColor { r: gray, g: gray, b: gray };
        }

        let q = if l < 0.5 { 
            l * (1.0 + s)
        } else {
            l + s - (l * s)
        };
        let p = (2.0 * l) - q;

        let r = Self::hue_to_rgb_component(p, q, h + (1.0/3.0));
        let g = Self::hue_to_rgb_component(p, q, h);
        let b = Self::hue_to_rgb_component(p, q, h - (1.0/3.0));

        let r = (r * 12000.0).round() / 12000.0;
        let g = (g * 12000.0).round() / 12000.0;
        let b = (b * 12000.0).round() / 12000.0;

        let r = (r * 255.0) as u8;
        let g = (g * 255.0) as u8;
        let b = (b * 255.0) as u8;
        
        RgbColor { r, g, b }
    } 

    fn hue_to_rgb_component(p: f32, q: f32, mut t: f32) -> f32 {
        
        if t < 0.0 {
            t += 1.0;
        }
        if t > 1.0 {
            t -= 1.0;
        }
        if t < (1.0/6.0) {
            return p + ((q - p) * 6.0 * t);
        }
        if t < (1.0/2.0) {
            return q;
        }
        if t < (2.0/3.0) {
            return p + ((q - p) * ((2.0/3.0) - t) * 6.0);
        }
        
        p
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn hsl_to_rgb_black() {
        let hsl = HslColor::new(0, 0, 0);
        let rgb: RgbColor = hsl.into();
        assert_eq!(rgb, RgbColor { r: 0, g: 0, b: 0 });
    }

    #[test]
    fn hsl_to_rgb_white() {
        let hsl = HslColor::new(0, 100, 100);
        let rgb: RgbColor = hsl.into();
        assert_eq!(rgb, RgbColor { r: 255, g: 255, b: 255 });
    }

    #[test]
    fn hsl_to_rgb_gray() {
        let hsl = HslColor::new(240, 0, 40);
        let rgb: RgbColor = hsl.into();
        assert!(rgb.r == rgb.g);
        assert!(rgb.g == rgb.b);
        assert!(rgb.r > 1);
    }

    #[test]
    fn hsl_to_rgb_red() {
        let hsl = HslColor::new(0, 100, 50);
        let rgb: RgbColor = hsl.into();
        assert_eq!(rgb, RgbColor { r: 255, g: 0, b: 0 });
    }

    #[test]
    fn hsl_to_rgb_green() {
        let hsl = HslColor::new(120, 100, 50);
        let rgb: RgbColor = hsl.into();
        assert_eq!(rgb, RgbColor { r: 0, g: 255, b: 0});
    }

    #[test]
    fn hsl_to_rgb_cyan() {
        let hsl = HslColor::new(180, 100, 50);
        let rgb: RgbColor = hsl.into();
        assert_eq!(rgb, RgbColor { r: 0, g: 255, b: 255});
    }

    #[test]
    fn hsl_to_rgb_overflow_cyan() {
        let hsl = HslColor::new(360 + 180, 100, 50);
        let rgb: RgbColor = hsl.into();
        assert_eq!(rgb, RgbColor { r: 0, g: 255, b: 255});
    }

    #[test]
    fn hsl_to_rgb_blue() {
        let hsl = HslColor::new(240, 100, 50);
        let rgb: RgbColor = hsl.into();
        assert_eq!(rgb, RgbColor { r: 0, g: 0, b: 255});
    }

    #[test]
    fn hsl_to_rgb_light_blue() {
        let hsl = HslColor::new(240, 100, 90);
        let rgb: RgbColor = hsl.into();
        assert!(rgb.r == rgb.g);
        assert!(rgb.b > rgb.r);
        assert!(rgb.b > 240);
    }

}