Skip to main content

bloq_utils/
color.rs

1use crate::{Basis, Pauli, PauliBasis};
2
3/// An 8-bit-per-channel RGBA color.
4///
5/// Every channel is `0..=255`; `a` is opacity, with `255` fully opaque.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
7pub struct RGBA {
8    /// Red channel.
9    pub r: u8,
10    /// Green channel.
11    pub g: u8,
12    /// Blue channel.
13    pub b: u8,
14    /// Alpha channel.
15    pub a: u8,
16}
17
18impl RGBA {
19    /// Softened red for the Pauli/basis `X` axis.
20    pub const X_RED: RGBA = RGBA::from_hex(0xFF7F7F, 255);
21    /// Softened green for the Pauli `Y` axis.
22    pub const Y_GREEN: RGBA = RGBA::from_hex(0x63C676, 255);
23    /// Softened blue for the Pauli/basis `Z` axis.
24    pub const Z_BLUE: RGBA = RGBA::from_hex(0x7396FF, 255);
25    /// Yellow for Hadamard blocks.
26    pub const H_YELLOW: RGBA = RGBA::from_hex(0xFFFF65, 255);
27    /// Magenta for T blocks, kept clear of [`Self::Y_GREEN`].
28    pub const T_PURPLE: RGBA = RGBA::from_hex(0xFF39C2, 255);
29    /// Opaque black for outlines and edges.
30    pub const LINE_BLACK: RGBA = RGBA::from_hex(0x000000, 255);
31    /// Semi-transparent light gray for unconnected ports.
32    pub const PORT_GRAY: RGBA = RGBA::from_hex(0xDDDDDD, 89);
33    /// Fully saturated red for the Pauli `X` axis.
34    pub const X_PURE_RED: RGBA = RGBA::from_hex(0xFF0000, 255);
35    /// Fully saturated green for the Pauli `Y` axis.
36    pub const Y_PURE_GREEN: RGBA = RGBA::from_hex(0x00FF00, 255);
37    /// Fully saturated blue for the Pauli `Z` axis.
38    pub const Z_PURE_BLUE: RGBA = RGBA::from_hex(0x0000FF, 255);
39
40    /// Builds a color from a packed `0xRRGGBB` value and a separate alpha.
41    pub const fn from_hex(rgb_hex: u32, alpha: u8) -> Self {
42        RGBA {
43            r: ((rgb_hex >> 16) & 0xFF) as u8,
44            g: ((rgb_hex >> 8) & 0xFF) as u8,
45            b: (rgb_hex & 0xFF) as u8,
46            a: alpha,
47        }
48    }
49
50    /// Converts to a normalized `[r, g, b, a]` array with each channel in `0.0..=1.0`.
51    pub const fn to_f32_array(self) -> [f32; 4] {
52        [
53            self.r as f32 / 255.0,
54            self.g as f32 / 255.0,
55            self.b as f32 / 255.0,
56            self.a as f32 / 255.0,
57        ]
58    }
59}
60
61impl From<Basis> for RGBA {
62    fn from(basis: Basis) -> Self {
63        match basis {
64            Basis::X => Self::X_RED,
65            Basis::Z => Self::Z_BLUE,
66        }
67    }
68}
69
70impl From<PauliBasis> for RGBA {
71    fn from(basis: PauliBasis) -> Self {
72        match basis {
73            PauliBasis::X => Self::X_RED,
74            PauliBasis::Y => Self::Y_GREEN,
75            PauliBasis::Z => Self::Z_BLUE,
76        }
77    }
78}
79
80impl From<Pauli> for RGBA {
81    fn from(pauli: Pauli) -> Self {
82        match pauli {
83            Pauli::I => RGBA::LINE_BLACK,
84            Pauli::X => Self::X_RED,
85            Pauli::Y => Self::Y_GREEN,
86            Pauli::Z => Self::Z_BLUE,
87        }
88    }
89}