use crate::{bindings::*, color::Color, math::BoundingBox};
#[derive(Debug, Clone)]
pub struct Rectangle {
pub color: Color,
pub corner_radii: CornerRadii,
}
#[derive(Debug, Clone)]
pub struct Text<'a> {
pub text: &'a str,
pub color: Color,
pub font_id: u16,
pub font_size: u16,
pub letter_spacing: u16,
pub line_height: u16,
}
#[derive(Debug, Clone)]
pub struct CornerRadii {
pub top_left: f32,
pub top_right: f32,
pub bottom_left: f32,
pub bottom_right: f32,
}
#[derive(Debug, Clone)]
pub struct BorderWidth {
pub left: u16,
pub right: u16,
pub top: u16,
pub bottom: u16,
pub between_children: u16,
}
#[derive(Debug, Clone)]
pub struct Border {
pub color: Color,
pub corner_radii: CornerRadii,
pub width: BorderWidth,
}
#[derive(Debug, Clone)]
pub struct Image<'a, ImageElementData> {
pub background_color: Color,
pub corner_radii: CornerRadii,
pub data: &'a ImageElementData,
}
#[derive(Debug, Clone)]
pub struct Custom<'a, CustomElementData> {
pub background_color: Color,
pub corner_radii: CornerRadii,
pub data: &'a CustomElementData,
}
impl From<Clay_RectangleRenderData> for Rectangle {
fn from(value: Clay_RectangleRenderData) -> Self {
Self {
color: value.backgroundColor.into(),
corner_radii: value.cornerRadius.into(),
}
}
}
impl From<Clay_TextRenderData> for Text<'_> {
fn from(value: Clay_TextRenderData) -> Self {
let text = unsafe {
core::str::from_utf8_unchecked(core::slice::from_raw_parts(
value.stringContents.chars as *const u8,
value.stringContents.length as _,
))
};
Self {
text,
color: value.textColor.into(),
font_id: value.fontId,
font_size: value.fontSize,
letter_spacing: value.letterSpacing,
line_height: value.lineHeight,
}
}
}
impl<ImageElementData> Image<'_, ImageElementData> {
pub(crate) unsafe fn from_clay_image_render_data(value: Clay_ImageRenderData) -> Self {
Self {
data: unsafe { &*value.imageData.cast() },
corner_radii: value.cornerRadius.into(),
background_color: value.backgroundColor.into(),
}
}
}
impl From<Clay_CornerRadius> for CornerRadii {
fn from(value: Clay_CornerRadius) -> Self {
Self {
top_left: value.topLeft,
top_right: value.topRight,
bottom_left: value.bottomLeft,
bottom_right: value.bottomRight,
}
}
}
impl From<Clay_BorderRenderData> for Border {
fn from(value: Clay_BorderRenderData) -> Self {
Self {
color: value.color.into(),
corner_radii: value.cornerRadius.into(),
width: BorderWidth {
left: value.width.left,
right: value.width.right,
top: value.width.top,
bottom: value.width.bottom,
between_children: value.width.betweenChildren,
},
}
}
}
impl<CustomElementData> Custom<'_, CustomElementData> {
pub(crate) unsafe fn from_clay_custom_element_data(value: Clay_CustomRenderData) -> Self {
Self {
background_color: value.backgroundColor.into(),
corner_radii: value.cornerRadius.into(),
data: unsafe { &*value.customData.cast() },
}
}
}
#[derive(Debug, Clone)]
pub enum RenderCommandConfig<'a, ImageElementData, CustomElementData> {
None(),
Rectangle(Rectangle),
Border(Border),
Text(Text<'a>),
Image(Image<'a, ImageElementData>),
ScissorStart(),
ScissorEnd(),
Custom(Custom<'a, CustomElementData>),
}
impl<ImageElementData, CustomElementData>
RenderCommandConfig<'_, ImageElementData, CustomElementData>
{
#[allow(non_upper_case_globals)]
pub(crate) unsafe fn from_clay_render_command(value: &Clay_RenderCommand) -> Self {
match value.commandType {
Clay_RenderCommandType_CLAY_RENDER_COMMAND_TYPE_NONE => Self::None(),
Clay_RenderCommandType_CLAY_RENDER_COMMAND_TYPE_RECTANGLE => {
Self::Rectangle(Rectangle::from(*unsafe { &value.renderData.rectangle }))
}
Clay_RenderCommandType_CLAY_RENDER_COMMAND_TYPE_TEXT => {
Self::Text(Text::from(*unsafe { &value.renderData.text }))
}
Clay_RenderCommandType_CLAY_RENDER_COMMAND_TYPE_BORDER => {
Self::Border(Border::from(*unsafe { &value.renderData.border }))
}
Clay_RenderCommandType_CLAY_RENDER_COMMAND_TYPE_IMAGE => {
Self::Image(unsafe { Image::from_clay_image_render_data(value.renderData.image) })
}
Clay_RenderCommandType_CLAY_RENDER_COMMAND_TYPE_SCISSOR_START => Self::ScissorStart(),
Clay_RenderCommandType_CLAY_RENDER_COMMAND_TYPE_SCISSOR_END => Self::ScissorEnd(),
Clay_RenderCommandType_CLAY_RENDER_COMMAND_TYPE_CUSTOM => Self::Custom(unsafe {
Custom::from_clay_custom_element_data(value.renderData.custom)
}),
_ => unreachable!(),
}
}
}
#[derive(Debug, Clone)]
pub struct RenderCommand<'a, ImageElementData, CustomElementData> {
pub bounding_box: BoundingBox,
pub config: RenderCommandConfig<'a, ImageElementData, CustomElementData>,
pub id: u32,
pub z_index: i16,
}
impl<ImageElementData, CustomElementData> RenderCommand<'_, ImageElementData, CustomElementData> {
pub(crate) unsafe fn from_clay_render_command(value: Clay_RenderCommand) -> Self {
Self {
id: value.id,
z_index: value.zIndex,
bounding_box: value.boundingBox.into(),
config: unsafe { RenderCommandConfig::from_clay_render_command(&value) },
}
}
}