1use crate::{
2 color::ColorU,
3 fonts::{FontId, GlyphId},
4 geometry::{rect::RectF, vector::Vector2F},
5};
6
7pub struct Scene {
8 scale_factor: f32,
9 layers: Vec<Layer>,
10 active_layer_stack: Vec<usize>,
11}
12
13#[derive(Default, Debug)]
14pub struct Layer {
15 clip_bounds: Option<RectF>,
16 quads: Vec<Quad>,
17 shadows: Vec<Shadow>,
18 glyphs: Vec<Glyph>,
19}
20
21#[derive(Default, Debug)]
22pub struct Quad {
23 pub bounds: RectF,
24 pub background: Option<ColorU>,
25 pub border: Border,
26 pub corner_radius: f32,
27}
28
29#[derive(Debug)]
30pub struct Shadow {
31 pub bounds: RectF,
32 pub corner_radius: f32,
33 pub sigma: f32,
34 pub color: ColorU,
35}
36
37#[derive(Debug)]
38pub struct Glyph {
39 pub font_id: FontId,
40 pub font_size: f32,
41 pub id: GlyphId,
42 pub origin: Vector2F,
43 pub color: ColorU,
44}
45
46#[derive(Clone, Copy, Default, Debug)]
47pub struct Border {
48 pub width: f32,
49 pub color: Option<ColorU>,
50 pub top: bool,
51 pub right: bool,
52 pub bottom: bool,
53 pub left: bool,
54}
55
56impl Scene {
57 pub fn new(scale_factor: f32) -> Self {
58 Scene {
59 scale_factor,
60 layers: vec![Layer::new(None)],
61 active_layer_stack: vec![0],
62 }
63 }
64
65 pub fn scale_factor(&self) -> f32 {
66 self.scale_factor
67 }
68
69 pub fn layers(&self) -> &[Layer] {
70 self.layers.as_slice()
71 }
72
73 pub fn push_layer(&mut self, clip_bounds: Option<RectF>) {
74 let ix = self.layers.len();
75 self.layers.push(Layer::new(clip_bounds));
76 self.active_layer_stack.push(ix);
77 }
78
79 pub fn pop_layer(&mut self) {
80 assert!(self.active_layer_stack.len() > 1);
81 self.active_layer_stack.pop();
82 }
83
84 pub fn push_quad(&mut self, quad: Quad) {
85 self.active_layer().push_quad(quad)
86 }
87
88 pub fn push_shadow(&mut self, shadow: Shadow) {
89 self.active_layer().push_shadow(shadow)
90 }
91
92 pub fn push_glyph(&mut self, glyph: Glyph) {
93 self.active_layer().push_glyph(glyph)
94 }
95
96 fn active_layer(&mut self) -> &mut Layer {
97 &mut self.layers[*self.active_layer_stack.last().unwrap()]
98 }
99}
100
101impl Layer {
102 pub fn new(clip_bounds: Option<RectF>) -> Self {
103 Self {
104 clip_bounds,
105 quads: Vec::new(),
106 shadows: Vec::new(),
107 glyphs: Vec::new(),
108 }
109 }
110
111 pub fn clip_bounds(&self) -> Option<RectF> {
112 self.clip_bounds
113 }
114
115 fn push_quad(&mut self, quad: Quad) {
116 self.quads.push(quad);
117 }
118
119 pub fn quads(&self) -> &[Quad] {
120 self.quads.as_slice()
121 }
122
123 fn push_shadow(&mut self, shadow: Shadow) {
124 self.shadows.push(shadow);
125 }
126
127 pub fn shadows(&self) -> &[Shadow] {
128 self.shadows.as_slice()
129 }
130
131 fn push_glyph(&mut self, glyph: Glyph) {
132 self.glyphs.push(glyph);
133 }
134
135 pub fn glyphs(&self) -> &[Glyph] {
136 self.glyphs.as_slice()
137 }
138}
139
140impl Border {
141 pub fn new(width: f32, color: impl Into<ColorU>) -> Self {
142 Self {
143 width,
144 color: Some(color.into()),
145 top: false,
146 left: false,
147 bottom: false,
148 right: false,
149 }
150 }
151
152 pub fn all(width: f32, color: impl Into<ColorU>) -> Self {
153 Self {
154 width,
155 color: Some(color.into()),
156 top: true,
157 left: true,
158 bottom: true,
159 right: true,
160 }
161 }
162
163 pub fn top(width: f32, color: impl Into<ColorU>) -> Self {
164 let mut border = Self::new(width, color);
165 border.top = true;
166 border
167 }
168
169 pub fn left(width: f32, color: impl Into<ColorU>) -> Self {
170 let mut border = Self::new(width, color);
171 border.left = true;
172 border
173 }
174
175 pub fn bottom(width: f32, color: impl Into<ColorU>) -> Self {
176 let mut border = Self::new(width, color);
177 border.bottom = true;
178 border
179 }
180
181 pub fn right(width: f32, color: impl Into<ColorU>) -> Self {
182 let mut border = Self::new(width, color);
183 border.right = true;
184 border
185 }
186
187 pub fn with_sides(mut self, top: bool, left: bool, bottom: bool, right: bool) -> Self {
188 self.top = top;
189 self.left = left;
190 self.bottom = bottom;
191 self.right = right;
192 self
193 }
194
195 fn all_sides(&self) -> bool {
196 self.top && self.left && self.bottom && self.right
197 }
198}