1use crate::{bindings::*, color::Color, math::BoundingBox};
2
3#[derive(Debug, Clone)]
5pub struct Rectangle {
6 pub color: Color,
8 pub corner_radii: CornerRadii,
10}
11
12#[derive(Debug, Clone)]
14pub struct Text<'a> {
15 pub text: &'a str,
17 pub color: Color,
19 pub font_id: u16,
21 pub font_size: u16,
23 pub letter_spacing: u16,
25 pub line_height: u16,
27}
28
29#[derive(Debug, Clone)]
31pub struct CornerRadii {
32 pub top_left: f32,
34 pub top_right: f32,
36 pub bottom_left: f32,
38 pub bottom_right: f32,
40}
41
42#[derive(Debug, Clone)]
44pub struct BorderWidth {
45 pub left: u16,
47 pub right: u16,
49 pub top: u16,
51 pub bottom: u16,
53 pub between_children: u16,
55}
56
57#[derive(Debug, Clone)]
59pub struct Border {
60 pub color: Color,
62 pub corner_radii: CornerRadii,
64 pub width: BorderWidth,
66}
67
68#[derive(Debug, Clone)]
70pub struct Image<'a, ImageElementData> {
71 pub background_color: Color,
73 pub corner_radii: CornerRadii,
75 pub data: &'a ImageElementData,
77}
78
79#[derive(Debug, Clone)]
81pub struct Custom<'a, CustomElementData> {
82 pub background_color: Color,
84 pub corner_radii: CornerRadii,
86 pub data: &'a CustomElementData,
88}
89
90impl From<Clay_RectangleRenderData> for Rectangle {
91 fn from(value: Clay_RectangleRenderData) -> Self {
92 Self {
93 color: value.backgroundColor.into(),
94 corner_radii: value.cornerRadius.into(),
95 }
96 }
97}
98
99impl From<Clay_TextRenderData> for Text<'_> {
100 fn from(value: Clay_TextRenderData) -> Self {
101 let text = unsafe {
102 core::str::from_utf8_unchecked(core::slice::from_raw_parts(
103 value.stringContents.chars as *const u8,
104 value.stringContents.length as _,
105 ))
106 };
107
108 Self {
109 text,
110 color: value.textColor.into(),
111 font_id: value.fontId,
112 font_size: value.fontSize,
113 letter_spacing: value.letterSpacing,
114 line_height: value.lineHeight,
115 }
116 }
117}
118
119impl<ImageElementData> Image<'_, ImageElementData> {
120 pub(crate) unsafe fn from_clay_image_render_data(value: Clay_ImageRenderData) -> Self {
121 Self {
122 data: unsafe { &*value.imageData.cast() },
123 corner_radii: value.cornerRadius.into(),
124 background_color: value.backgroundColor.into(),
125 }
126 }
127}
128
129impl From<Clay_CornerRadius> for CornerRadii {
130 fn from(value: Clay_CornerRadius) -> Self {
131 Self {
132 top_left: value.topLeft,
133 top_right: value.topRight,
134 bottom_left: value.bottomLeft,
135 bottom_right: value.bottomRight,
136 }
137 }
138}
139
140impl From<Clay_BorderRenderData> for Border {
141 fn from(value: Clay_BorderRenderData) -> Self {
142 Self {
143 color: value.color.into(),
144 corner_radii: value.cornerRadius.into(),
145
146 width: BorderWidth {
147 left: value.width.left,
148 right: value.width.right,
149 top: value.width.top,
150 bottom: value.width.bottom,
151 between_children: value.width.betweenChildren,
152 },
153 }
154 }
155}
156
157impl<CustomElementData> Custom<'_, CustomElementData> {
158 pub(crate) unsafe fn from_clay_custom_element_data(value: Clay_CustomRenderData) -> Self {
159 Self {
160 background_color: value.backgroundColor.into(),
161 corner_radii: value.cornerRadius.into(),
162 data: unsafe { &*value.customData.cast() },
163 }
164 }
165}
166
167#[derive(Debug, Clone)]
168pub enum RenderCommandConfig<'a, ImageElementData, CustomElementData> {
169 None(),
170 Rectangle(Rectangle),
171 Border(Border),
172 Text(Text<'a>),
173 Image(Image<'a, ImageElementData>),
174 ScissorStart(),
175 ScissorEnd(),
176 Custom(Custom<'a, CustomElementData>),
177}
178
179impl<ImageElementData, CustomElementData>
180 RenderCommandConfig<'_, ImageElementData, CustomElementData>
181{
182 #[allow(non_upper_case_globals)]
183 pub(crate) unsafe fn from_clay_render_command(value: &Clay_RenderCommand) -> Self {
184 match value.commandType {
185 Clay_RenderCommandType_CLAY_RENDER_COMMAND_TYPE_NONE => Self::None(),
186 Clay_RenderCommandType_CLAY_RENDER_COMMAND_TYPE_RECTANGLE => {
187 Self::Rectangle(Rectangle::from(*unsafe { &value.renderData.rectangle }))
188 }
189 Clay_RenderCommandType_CLAY_RENDER_COMMAND_TYPE_TEXT => {
190 Self::Text(Text::from(*unsafe { &value.renderData.text }))
191 }
192 Clay_RenderCommandType_CLAY_RENDER_COMMAND_TYPE_BORDER => {
193 Self::Border(Border::from(*unsafe { &value.renderData.border }))
194 }
195 Clay_RenderCommandType_CLAY_RENDER_COMMAND_TYPE_IMAGE => {
196 Self::Image(unsafe { Image::from_clay_image_render_data(value.renderData.image) })
197 }
198 Clay_RenderCommandType_CLAY_RENDER_COMMAND_TYPE_SCISSOR_START => Self::ScissorStart(),
199 Clay_RenderCommandType_CLAY_RENDER_COMMAND_TYPE_SCISSOR_END => Self::ScissorEnd(),
200 Clay_RenderCommandType_CLAY_RENDER_COMMAND_TYPE_CUSTOM => Self::Custom(unsafe {
201 Custom::from_clay_custom_element_data(value.renderData.custom)
202 }),
203 _ => unreachable!(),
204 }
205 }
206}
207
208#[derive(Debug, Clone)]
210pub struct RenderCommand<'a, ImageElementData, CustomElementData> {
211 pub bounding_box: BoundingBox,
213 pub config: RenderCommandConfig<'a, ImageElementData, CustomElementData>,
215 pub id: u32,
217 pub z_index: i16,
220}
221
222impl<ImageElementData, CustomElementData> RenderCommand<'_, ImageElementData, CustomElementData> {
223 pub(crate) unsafe fn from_clay_render_command(value: Clay_RenderCommand) -> Self {
224 Self {
225 id: value.id,
226 z_index: value.zIndex,
227 bounding_box: value.boundingBox.into(),
228 config: unsafe { RenderCommandConfig::from_clay_render_command(&value) },
229 }
230 }
231}