Files
ab_glyph_rasterizer
addr2line
adler
andrew
approx
arrayvec
ash
atom
backtrace
bitflags
byteorder
calloop
cfg_if
colorful
conrod_core
conrod_derive
conrod_example_shared
conrod_gfx
conrod_glium
conrod_piston
conrod_rendy
conrod_vulkano
conrod_wgpu
conrod_winit
copyless
copypasta
crossbeam
crossbeam_channel
crossbeam_deque
crossbeam_epoch
crossbeam_queue
crossbeam_utils
daggy
dlib
downcast_rs
draw_state
either
fixedbitset
float
fnv
futures
futures_channel
futures_core
futures_executor
futures_io
futures_macro
futures_sink
futures_task
futures_util
async_await
future
io
lock
sink
stream
task
fxhash
getrandom
gfx
gfx_backend_empty
gfx_backend_vulkan
gfx_core
gfx_descriptor
gfx_hal
gfx_memory
gimli
glium
glutin
glutin_egl_sys
glutin_glx_sys
graphics
half
hibitset
inplace_it
input
instant
interpolation
iovec
itoa
lazy_static
lazycell
libc
libloading
line_drawing
linked_hash_map
lock_api
log
maybe_uninit
memchr
memmap
memoffset
miniz_oxide
mio
mio_extras
naga
net2
nix
nom
num
num_bigint
num_complex
num_cpus
num_integer
num_iter
num_rational
num_traits
object
once_cell
ordered_float
ordermap
osmesa_sys
owned_ttf_parser
parking_lot
parking_lot_core
percent_encoding
petgraph
pin_project
pin_project_internal
pin_project_lite
pin_utils
ppv_lite86
proc_macro2
proc_macro_hack
proc_macro_nested
quote
rand
rand_chacha
rand_core
raw_window_handle
read_color
relevant
rendy
rendy_chain
rendy_command
rendy_core
rendy_descriptor
rendy_factory
rendy_frame
rendy_graph
rendy_init
rendy_memory
rendy_mesh
rendy_resource
rendy_shader
rendy_texture
rendy_wsi
rustc_demangle
rustc_hash
rusttype
ryu
same_file
scoped_tls
scopeguard
serde
serde_derive
serde_json
shaderc
shaderc_sys
shared_library
slab
smallvec
smithay_client_toolkit
smithay_clipboard
spirv_headers
stb_truetype
syn
takeable_option
texture
thiserror
thiserror_impl
thread_profiler
time
tracing
tracing_core
ttf_parser
typed_arena
unicode_xid
vecmath
viewport
vk_sys
void
vulkano
buffer
command_buffer
descriptor
device
framebuffer
image
instance
memory
pipeline
query
swapchain
sync
vulkano_shaders
walkdir
wayland_client
wayland_commons
wayland_cursor
wayland_egl
wayland_protocols
wayland_sys
wgpu
wgpu_core
wgpu_types
winit
x11
x11_clipboard
x11_dl
xcb
xcursor
xdg
xml
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
use core::ColorInterface;
use core::rgb::RGB;

#[derive(Debug, Copy, Clone, PartialEq)]
pub struct HSL {
    // range 0 ≤ H < 1.0, 0 ≤ S ≤ 1.0 and 0 ≤ L ≤ 1.0:
    pub h: f32,
    s: f32,
    l: f32,
}

impl HSL {
    pub fn new(h: f32, s: f32, l: f32) -> HSL {
        HSL { h: _round(h), s: _round(s), l: _round(l) }
    }

    pub fn hsl_to_rgb(&self) -> RGB {
        let red: f32;
        let green: f32;
        let blue: f32;
        let var_1: f32;
        let var_2: f32;
        if self.s == 0.0 {
            let tmp = self.l * 255.0;
            red = tmp;
            green = tmp;
            blue = tmp;
        } else {
            if self.l < 0.5 {
                var_2 = self.l * (1.0 + self.s);
            } else {
                var_2 = (self.l + self.s) - (self.s * self.l);
            }
            var_1 = 2.0 * self.l - var_2;
            red = 255.0 * hue_2_rgb(var_1, var_2, &mut (self.h + (1.0 / 3.0)));
            green = 255.0 * hue_2_rgb(var_1, var_2, &mut self.h.clone());
            blue = 255.0 * hue_2_rgb(var_1, var_2, &mut (self.h - (1.0 / 3.0)));
        }
        RGB::new(red.round() as u8, green.round() as u8, blue.round() as u8)
    }
}

impl ColorInterface for HSL {
    fn to_color_str(&self) -> String {
        self.hsl_to_rgb().to_color_str()
    }
    fn to_hsl(&self) -> HSL { *self }
}

fn hue_2_rgb(v1: f32, v2: f32, vh: &mut f32) -> f32 {
    if *vh < 0.0 {
        *vh += 1.0;
    }
    if *vh > 1.0 {
        *vh -= 1.0;
    }
    if 6.0 * *vh < 1.0 {
        return v1 + (v2 - v1) * 6.0 * *vh;
    }
    if 2.0 * *vh < 1.0 {
        return v2;
    }
    if 3.0 * *vh < 2.0 {
        return v1 + (v2 - v1) * (2.0 / 3.0 - *vh) * 6.0;
    }
    v1
}

fn _round(value: f32) -> f32 {
    if value < 0.0 {
        0.0
    } else if value >= 1.0 {
        1.0
    } else {
        value
    }
}

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

    #[test]
    fn test_hsl_2_rgb_1() {
        let hsl = HSL::new(0.7, 0.50, 0.60);
        let rgb = RGB::new(122, 102, 204);

        assert_eq!(rgb, hsl.hsl_to_rgb());
    }

    #[test]
    fn test_hsl_2_rgb_2() {
        let hsl = HSL::new(0.7, 0.0, 0.60);
        let rgb = RGB::new(153, 153, 153);
        assert_eq!(rgb, hsl.hsl_to_rgb());
    }

    #[test]
    fn test_hsl_2_rgb_3() {
        let hsl = HSL::new(0.7, 0.50, 0.30);
        let rgb = RGB::new(54, 38, 115);

        assert_eq!(rgb, hsl.hsl_to_rgb());
    }
}