lbf/io/
svg_util.rs

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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
use std::convert::Into;
use std::fmt::{Display, Formatter};

use serde::{Deserialize, Deserializer, Serialize, Serializer};

use jagua_rs::entities::quality_zone::N_QUALITIES;
use jagua_rs::fsize;

#[derive(Clone, PartialEq, Debug, Serialize, Deserialize, Copy, Default)]
pub struct SvgDrawOptions {
    ///The theme to use for the svg
    #[serde(default)]
    pub theme: SvgLayoutTheme,
    ///Draw the quadtree on top
    #[serde(default)]
    pub quadtree: bool,
    ///Draw the hazard proximity grid on top
    #[serde(default)]
    pub haz_prox_grid: bool,
    ///Draw the fail fast surrogate on top of each item
    #[serde(default)]
    pub surrogate: bool,
}

#[derive(Clone, PartialEq, Debug, Serialize, Deserialize, Copy)]
pub struct SvgLayoutTheme {
    pub stroke_width_multiplier: fsize,
    pub bin_fill: Color,
    pub item_fill: Color,
    pub hole_fill: Color,
    pub qz_fill: [Color; N_QUALITIES],
    pub qz_stroke_opac: fsize,
}

impl Default for SvgLayoutTheme {
    fn default() -> Self {
        Self::earth_tones()
    }
}

impl SvgLayoutTheme {
    pub fn earth_tones() -> Self {
        SvgLayoutTheme {
            stroke_width_multiplier: 2.0,
            bin_fill: "#CC824A".into(),
            item_fill: "#FFC879".into(),
            hole_fill: "#2D2D2D".into(),
            qz_fill: [
                "#000000".into(), //BLACK
                "#FF0000".into(), //RED
                "#FF5E00".into(), //ORANGE
                "#FFA500".into(), //LIGHT ORANGE
                "#C7A900".into(), //DARK YELLOW
                "#FFFF00".into(), //YELLOW
                "#CBFF00".into(), //GREEN
                "#CBFF00".into(), //GREEN
                "#CBFF00".into(), //GREEN
                "#CBFF00".into(), //GREEN
            ],
            qz_stroke_opac: 0.5,
        }
    }

    pub fn gray() -> Self {
        SvgLayoutTheme {
            stroke_width_multiplier: 2.5,
            bin_fill: "#C3C3C3".into(),
            item_fill: "#8F8F8F".into(),
            hole_fill: "#FFFFFF".into(),
            qz_fill: [
                "#636363".into(), //GRAY
                "#636363".into(), //GRAY
                "#636363".into(), //GRAY
                "#636363".into(), //GRAY
                "#636363".into(), //GRAY
                "#636363".into(), //GRAY
                "#636363".into(), //GRAY
                "#636363".into(), //GRAY
                "#636363".into(), //GRAY
                "#636363".into(), //GRAY
            ],
            qz_stroke_opac: 0.9,
        }
    }
}

pub fn change_brightness(color: Color, fraction: fsize) -> Color {
    let Color(r, g, b) = color;

    let r = (r as fsize * fraction) as u8;
    let g = (g as fsize * fraction) as u8;
    let b = (b as fsize * fraction) as u8;
    Color(r, g, b)
}

pub fn blend_colors(color_1: Color, color_2: Color) -> Color {
    //blend color_1 and color_2
    let Color(r_1, g_1, b_1) = color_1;
    let Color(r_2, g_2, b_2) = color_2;

    let r = ((r_1 as fsize * 0.5) + (r_2 as fsize * 0.5)) as u8;
    let g = ((g_1 as fsize * 0.5) + (g_2 as fsize * 0.5)) as u8;
    let b = ((b_1 as fsize * 0.5) + (b_2 as fsize * 0.5)) as u8;

    Color(r, g, b)
}

#[derive(Copy, Clone, PartialEq, Debug)]
pub struct Color(u8, u8, u8);

impl Display for Color {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "#{:02X}{:02X}{:02X}", self.0, self.1, self.2)
    }
}

impl From<String> for Color {
    fn from(mut s: String) -> Self {
        if s.starts_with('#') {
            s.remove(0);
        }
        let r = u8::from_str_radix(&s[0..2], 16).unwrap();
        let g = u8::from_str_radix(&s[2..4], 16).unwrap();
        let b = u8::from_str_radix(&s[4..6], 16).unwrap();
        Color(r, g, b)
    }
}

impl From<&str> for Color {
    fn from(s: &str) -> Self {
        Color::from(s.to_owned())
    }
}

impl Serialize for Color {
    fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(&format!("{self}"))
    }
}

impl<'de> Deserialize<'de> for Color {
    fn deserialize<D>(deserializer: D) -> Result<Self, <D as Deserializer<'de>>::Error>
    where
        D: Deserializer<'de>,
    {
        let s = String::deserialize(deserializer)?;
        Ok(Color::from(s))
    }
}