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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
use rootvg_core::color::PackedSrgb;
use rootvg_core::gradient::{Gradient, PackedGradient};
use rootvg_core::math::{Point, Rect, Size};

use crate::border::Border;
use crate::Radius;

/// A quad primitive with a gradient background.
#[derive(Default, Debug, Clone, Copy, PartialEq)]
pub struct GradientQuad {
    /// The bounds of the quad in logical points.
    pub bounds: Rect,
    /// The background color of the quad
    pub bg_gradient: Gradient,
    /// The [`Border`] of the quad
    pub border: Border,
    /*
    /// The shadow of the quad
    pub shadow: Shadow,
    */
}

impl GradientQuad {
    pub fn packed(&self) -> GradientQuadPrimitive {
        GradientQuadPrimitive {
            gradient: self.bg_gradient.packed(self.bounds),
            position: self.bounds.origin.into(),
            size: self.bounds.size.into(),
            border_color: self.border.color,
            border_radius: self.border.radius.into(),
            border_width: self.border.width,
        }
    }

    pub fn builder(size: Size) -> GradientQuadBuilder {
        GradientQuadBuilder::new(size)
    }
}

pub struct GradientQuadBuilder {
    quad: GradientQuad,
}

impl GradientQuadBuilder {
    pub fn new(size: Size) -> Self {
        Self {
            quad: GradientQuad {
                bounds: Rect {
                    origin: Point::new(0.0, 0.0),
                    size,
                },
                ..Default::default()
            },
        }
    }

    pub fn position(mut self, position: Point) -> Self {
        self.quad.bounds.origin = position;
        self
    }

    pub fn bg_gradient(mut self, color: impl Into<Gradient>) -> Self {
        self.quad.bg_gradient = color.into();
        self
    }

    pub fn border_color(mut self, color: impl Into<PackedSrgb>) -> Self {
        self.quad.border.color = color.into();
        self
    }

    pub fn border_width(mut self, width: f32) -> Self {
        self.quad.border.width = width;
        self
    }

    pub fn border_radius(mut self, radius: impl Into<Radius>) -> Self {
        self.quad.border.radius = radius.into();
        self
    }

    pub fn border(mut self, border: Border) -> Self {
        self.quad.border = border;
        self
    }

    /*
    pub fn shadow_color(mut self, color: impl Into<PackedSrgb>) -> Self {
        self.quad.shadow.color = color.into();
        self
    }

    pub fn shadow_offset(mut self, offset: Point) -> Self {
        self.quad.shadow.offset = offset;
        self
    }

    pub fn blur_radius(mut self, blur_radius: f32) -> Self {
        self.quad.shadow.blur_radius = blur_radius;
        self
    }

    pub fn shadow(mut self, shadow: Shadow) -> Self {
        self.quad.shadow = shadow;
        self
    }
    */

    pub fn build(self) -> GradientQuad {
        self.quad
    }
}

/// A quad primitive with a gradient background, packed into a format
/// for use in rendering.
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, bytemuck::Zeroable, bytemuck::Pod)]
pub struct GradientQuadPrimitive {
    /// The background gradient data of the quad.
    pub gradient: PackedGradient,

    /// The position of the [`Quad`] in logical points.
    pub position: [f32; 2],

    /// The size of the [`Quad`] in logical points.
    pub size: [f32; 2],

    /// The border color of the [`Quad`], in __linear RGB__.
    pub border_color: PackedSrgb,

    /// The border radii of the [`Quad`] in logical points.
    pub border_radius: [f32; 4],

    /// The border width of the [`Quad`] in logical points.
    pub border_width: f32,
}

impl GradientQuadPrimitive {
    pub fn new(quad: &GradientQuad) -> Self {
        Self {
            gradient: quad.bg_gradient.packed(quad.bounds),
            position: quad.bounds.origin.into(),
            size: quad.bounds.size.into(),
            border_color: quad.border.color,
            border_radius: quad.border.radius.into(),
            border_width: quad.border.width,
        }
    }
}

impl From<GradientQuad> for GradientQuadPrimitive {
    fn from(q: GradientQuad) -> GradientQuadPrimitive {
        q.packed()
    }
}

impl<'a> From<&'a GradientQuad> for GradientQuadPrimitive {
    fn from(q: &'a GradientQuad) -> GradientQuadPrimitive {
        q.packed()
    }
}

impl From<GradientQuadBuilder> for GradientQuadPrimitive {
    fn from(q: GradientQuadBuilder) -> GradientQuadPrimitive {
        q.build().packed()
    }
}

impl From<GradientQuadBuilder> for GradientQuad {
    fn from(q: GradientQuadBuilder) -> GradientQuad {
        q.build()
    }
}