1use cotis_defaults::colors::Color;
32#[cfg(feature = "complex-color")]
33use cotis_defaults::colors::ColorLayer;
34use cotis_defaults::render_commands::render_t_list::{IsRenderList, RenderTList};
35use cotis_defaults::render_commands::*;
36use glyphon::Color as GlyphColor;
37
38use crate::color::cotis_color_to_ui_color;
39use crate::drawable::{WgpuDrawContext, WgpuDrawable};
40use crate::pipeline::{UIBorderThickness, UICornerRadii, UIPosition};
41
42impl<T: WgpuDrawable, L: IsRenderList + WgpuDrawable> WgpuDrawable for RenderTList<T, L> {
44 fn draw(self: Box<Self>, ctx: &mut WgpuDrawContext<'_>) {
45 match *self {
46 RenderTList::Type(command) => Box::new(command).draw(ctx),
47 RenderTList::List(list) => Box::new(list).draw(ctx),
48 }
49 }
50}
51
52impl<T: WgpuDrawable> WgpuDrawable for RenderTList<T, ()> {
54 fn draw(self: Box<Self>, ctx: &mut WgpuDrawContext<'_>) {
55 match *self {
56 RenderTList::Type(command) => Box::new(command).draw(ctx),
57 RenderTList::List(()) => {}
58 }
59 }
60}
61
62impl<'a, ExtraData> WgpuDrawable for Rectangle<'a, ExtraData> {
64 fn draw(self: Box<Self>, ctx: &mut WgpuDrawContext<'_>) {
65 let bb = self.info.bounding_box;
66 let color = resolve_rectangle_color(self.as_ref());
67 ctx.geometry.filled_rectangle(
68 UIPosition {
69 x: bb.x,
70 y: bb.y,
71 z: *ctx.depth,
72 },
73 UIPosition {
74 x: bb.width,
75 y: bb.height,
76 z: *ctx.depth,
77 },
78 color,
79 corner_radii_to_ui(&self.corner_radii),
80 );
81 *ctx.depth -= 0.000_1;
82 }
83}
84
85impl<'a, ExtraData> WgpuDrawable for Border<'a, ExtraData> {
87 fn draw(self: Box<Self>, ctx: &mut WgpuDrawContext<'_>) {
88 let bb = self.info.bounding_box;
89 ctx.geometry.rectangle(
90 UIPosition {
91 x: bb.x,
92 y: bb.y,
93 z: *ctx.depth,
94 },
95 UIPosition {
96 x: bb.width,
97 y: bb.height,
98 z: *ctx.depth,
99 },
100 UIBorderThickness {
101 top: self.width.top,
102 left: self.width.left,
103 bottom: self.width.bottom,
104 right: self.width.right,
105 },
106 cotis_color_to_ui_color(self.color),
107 corner_radii_to_ui(&self.corner_radii),
108 );
109 *ctx.depth -= 0.000_1;
110 }
111}
112
113impl<'a, ExtraData> WgpuDrawable for Text<'a, ExtraData> {
118 fn draw(self: Box<Self>, ctx: &mut WgpuDrawContext<'_>) {
119 let bb = self.info.bounding_box;
120 let color = resolve_text_color(self.as_ref());
121 let line_height = if self.line_height > 0.0 {
122 self.line_height * ctx.dpi_scale
123 } else {
124 self.font_size * 1.5 * ctx.dpi_scale
125 };
126
127 let scissor_bounds = if ctx.scissor_active {
128 Some((ctx.scissor_position, ctx.scissor_bounds))
129 } else {
130 None
131 };
132
133 ctx.text.queue_text(
134 self.text.as_ref(),
135 self.font_size * ctx.dpi_scale,
136 line_height,
137 UIPosition {
138 x: bb.x,
139 y: bb.y,
140 z: *ctx.depth,
141 },
142 scissor_bounds,
143 color,
144 *ctx.depth,
145 );
146 *ctx.depth -= 0.000_1;
147 }
148}
149
150impl<'a, ImageElementData, ExtraData> WgpuDrawable for Image<'a, ImageElementData, ExtraData> {
154 fn draw(self: Box<Self>, ctx: &mut WgpuDrawContext<'_>) {
155 let bb = self.info.bounding_box;
156 let color = resolve_image_background_color(self.as_ref());
157 ctx.geometry.filled_rectangle(
158 UIPosition {
159 x: bb.x,
160 y: bb.y,
161 z: *ctx.depth,
162 },
163 UIPosition {
164 x: bb.width,
165 y: bb.height,
166 z: *ctx.depth,
167 },
168 color,
169 corner_radii_to_ui(&self.corner_radii),
170 );
171 *ctx.depth -= 0.000_1;
172 }
173}
174
175impl<'a, ExtraData> WgpuDrawable for ClipStart<'a, ExtraData> {
179 fn draw(self: Box<Self>, ctx: &mut WgpuDrawContext<'_>) {
180 let bb = self.info.bounding_box;
181 ctx.scissor_position = UIPosition {
182 x: bb.x,
183 y: bb.y,
184 z: 0.0,
185 };
186 ctx.scissor_bounds = UIPosition {
187 x: bb.width.max(0.0),
188 y: bb.height.max(0.0),
189 z: 0.0,
190 };
191 ctx.scissor_active = self.horizontal || self.vertical;
192 *ctx.depth -= 0.000_1;
193 }
194}
195
196impl WgpuDrawable for ClipEnd {
198 fn draw(self: Box<Self>, ctx: &mut WgpuDrawContext<'_>) {
199 let _ = self;
200 ctx.scissor_active = false;
201 *ctx.depth -= 0.000_1;
202 }
203}
204
205fn corner_radii_to_ui(radii: &CornerRadii) -> UICornerRadii {
206 UICornerRadii {
207 top_left: radii.top_left,
208 top_right: radii.top_right,
209 bottom_left: radii.bottom_left,
210 bottom_right: radii.bottom_right,
211 }
212}
213
214#[cfg(not(feature = "complex-color"))]
215fn resolve_rectangle_color<ExtraData>(
216 rectangle: &Rectangle<'_, ExtraData>,
217) -> crate::pipeline::UIColor {
218 cotis_color_to_ui_color(rectangle.color)
219}
220
221#[cfg(feature = "complex-color")]
222fn resolve_rectangle_color<ExtraData>(
223 rectangle: &Rectangle<'_, ExtraData>,
224) -> crate::pipeline::UIColor {
225 cotis_color_to_ui_color(color_layer_to_solid(&rectangle.color))
226}
227
228#[cfg(not(feature = "complex-color"))]
229fn resolve_image_background_color<ImageElementData, ExtraData>(
230 image: &Image<'_, ImageElementData, ExtraData>,
231) -> crate::pipeline::UIColor {
232 cotis_color_to_ui_color(image.background_color)
233}
234
235#[cfg(feature = "complex-color")]
236fn resolve_image_background_color<ImageElementData, ExtraData>(
237 image: &Image<'_, ImageElementData, ExtraData>,
238) -> crate::pipeline::UIColor {
239 cotis_color_to_ui_color(color_layer_to_solid(&image.background_color))
240}
241
242#[cfg(not(feature = "complex-color"))]
243fn resolve_text_color<ExtraData>(text: &Text<'_, ExtraData>) -> GlyphColor {
244 cotis_color_to_glyph(text.color)
245}
246
247#[cfg(feature = "complex-color")]
248fn resolve_text_color<ExtraData>(text: &Text<'_, ExtraData>) -> GlyphColor {
249 cotis_color_to_glyph(color_layer_to_solid(&text.color))
250}
251
252fn cotis_color_to_glyph(color: Color) -> GlyphColor {
253 GlyphColor::rgba(
254 color.r.round() as u8,
255 color.g.round() as u8,
256 color.b.round() as u8,
257 color.a.round() as u8,
258 )
259}
260
261#[cfg(feature = "complex-color")]
262fn color_layer_to_solid(layer: &ColorLayer) -> Color {
263 match layer {
264 ColorLayer::Solid(color) => *color,
265 ColorLayer::Linear(_) | ColorLayer::Radial(_) | ColorLayer::RoundedRect(_) => {
266 Color::rgba(0.0, 0.0, 0.0, 0.0)
267 }
268 ColorLayer::Layered(layered) => layered
269 .layers
270 .first()
271 .map(color_layer_to_solid)
272 .unwrap_or_else(|| Color::rgba(0.0, 0.0, 0.0, 0.0)),
273 }
274}