use super::text_measurer::LineFit;
use super::types::{Gradient, Shadow};
use crate::image_decode::DecodedImage;
use crate::widgets::font::{FontFamily, FontWeight, LineHeight};
use crate::widgets::image::{ContentFit, ImageSource};
use crate::widgets::text_style::TextStroke;
use crate::widgets::{Color, Rect, TextAlign};
#[derive(Debug, Clone, Copy)]
pub struct Border {
pub width: f32,
pub color: Color,
}
impl Border {
pub fn new(width: f32, color: Color) -> Self {
Self { width, color }
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct CornerRadii {
pub top_left: f32,
pub top_right: f32,
pub bottom_right: f32,
pub bottom_left: f32,
}
impl CornerRadii {
pub fn permuted(&self, permutation: [usize; 4]) -> Self {
let from = self.to_array();
let mut to = [0.0; 4];
for (i, &dest) in permutation.iter().enumerate() {
to[dest] = from[i];
}
Self {
top_left: to[0],
top_right: to[1],
bottom_right: to[2],
bottom_left: to[3],
}
}
pub fn uniform(radius: f32) -> Self {
Self {
top_left: radius,
top_right: radius,
bottom_right: radius,
bottom_left: radius,
}
}
pub fn top(radius: f32) -> Self {
Self {
top_left: radius,
top_right: radius,
bottom_right: 0.0,
bottom_left: 0.0,
}
}
pub fn bottom(radius: f32) -> Self {
Self {
top_left: 0.0,
top_right: 0.0,
bottom_right: radius,
bottom_left: radius,
}
}
pub fn max(&self) -> f32 {
self.top_left
.max(self.top_right)
.max(self.bottom_right)
.max(self.bottom_left)
}
pub fn to_array(self) -> [f32; 4] {
[
self.top_left,
self.top_right,
self.bottom_right,
self.bottom_left,
]
}
pub fn scaled(self, factor: f32) -> Self {
Self {
top_left: self.top_left * factor,
top_right: self.top_right * factor,
bottom_right: self.bottom_right * factor,
bottom_left: self.bottom_left * factor,
}
}
}
impl From<f32> for CornerRadii {
fn from(radius: f32) -> Self {
Self::uniform(radius)
}
}
impl From<f64> for CornerRadii {
fn from(radius: f64) -> Self {
Self::uniform(radius as f32)
}
}
impl From<i32> for CornerRadii {
fn from(radius: i32) -> Self {
Self::uniform(radius as f32)
}
}
impl From<u32> for CornerRadii {
fn from(radius: u32) -> Self {
Self::uniform(radius as f32)
}
}
impl From<u16> for CornerRadii {
fn from(radius: u16) -> Self {
Self::uniform(radius as f32)
}
}
impl From<[f32; 2]> for CornerRadii {
fn from(v: [f32; 2]) -> Self {
Self {
top_left: v[0],
top_right: v[0],
bottom_right: v[1],
bottom_left: v[1],
}
}
}
impl From<[f32; 4]> for CornerRadii {
fn from(v: [f32; 4]) -> Self {
Self {
top_left: v[0],
top_right: v[1],
bottom_right: v[2],
bottom_left: v[3],
}
}
}
impl From<[i32; 2]> for CornerRadii {
fn from(v: [i32; 2]) -> Self {
[v[0] as f32, v[1] as f32].into()
}
}
impl From<[i32; 4]> for CornerRadii {
fn from(v: [i32; 4]) -> Self {
[v[0] as f32, v[1] as f32, v[2] as f32, v[3] as f32].into()
}
}
impl From<(f32, f32, f32, f32)> for CornerRadii {
fn from(r: (f32, f32, f32, f32)) -> Self {
Self {
top_left: r.0,
top_right: r.1,
bottom_right: r.2,
bottom_left: r.3,
}
}
}
#[derive(Debug, Clone)]
pub enum DrawCommand {
RoundedRect {
rect: Rect,
color: Color,
radius: CornerRadii,
curvature: f32,
border: Option<Border>,
shadow: Option<Shadow>,
gradient: Option<Gradient>,
},
Circle {
center: (f32, f32),
radius: f32,
color: Color,
},
Text {
text: std::rc::Rc<str>,
rect: Rect,
color: Color,
font_size: f32,
font_family: FontFamily,
font_weight: FontWeight,
line_height: LineHeight,
letter_spacing: f32,
align: TextAlign,
fit: Option<LineFit>,
},
InputRegion {
rect: Rect,
corner_radii: CornerRadii,
curvature: f32,
takes: bool,
},
BackdropBlur {
rect: Rect,
sources: crate::backdrop::BackdropSources,
radius: f32,
corner_radii: CornerRadii,
curvature: f32,
},
TextBackdropBlur {
text: String,
stroke: Option<TextStroke>,
rect: Rect,
radius: f32,
font_size: f32,
font_family: FontFamily,
font_weight: FontWeight,
line_height: LineHeight,
letter_spacing: f32,
align: TextAlign,
fit: Option<LineFit>,
},
Image {
source: ImageSource,
decoded: Option<DecodedImage>,
rect: Rect,
content_fit: ContentFit,
tint: Option<Color>,
},
}
impl DrawCommand {
pub fn rounded_rect(rect: Rect, color: Color, radius: impl Into<CornerRadii>) -> Self {
Self::RoundedRect {
rect,
color,
radius: radius.into(),
curvature: 1.0,
border: None,
shadow: None,
gradient: None,
}
}
pub fn rounded_rect_with_curvature(
rect: Rect,
color: Color,
radius: impl Into<CornerRadii>,
curvature: f32,
) -> Self {
Self::RoundedRect {
rect,
color,
radius: radius.into(),
curvature,
border: None,
shadow: None,
gradient: None,
}
}
pub fn circle(center: (f32, f32), radius: f32, color: Color) -> Self {
Self::Circle {
center,
radius,
color,
}
}
}