use waterui_color::ResolvedColor;
use waterui_core::layout::Point;
use vello::peniko;
use super::conversions::{point_to_kurbo, resolved_color_to_peniko};
#[derive(Debug, Clone)]
pub struct ColorStop {
pub offset: f32,
pub color: ResolvedColor,
}
impl ColorStop {
#[must_use]
pub fn new(offset: f32, color: impl Into<ResolvedColor>) -> Self {
Self {
offset,
color: color.into(),
}
}
}
#[derive(Debug, Clone)]
pub struct LinearGradient {
start: Point,
end: Point,
stops: Vec<ColorStop>,
}
impl LinearGradient {
#[must_use]
pub const fn new(x0: f32, y0: f32, x1: f32, y1: f32) -> Self {
Self {
start: Point::new(x0, y0),
end: Point::new(x1, y1),
stops: Vec::new(),
}
}
pub fn add_color_stop(&mut self, offset: f32, color: impl Into<ResolvedColor>) {
self.stops.push(ColorStop::new(offset, color));
}
#[must_use]
pub(crate) fn build(&self) -> peniko::Brush {
let peniko_stops: Vec<peniko::ColorStop> = self
.stops
.iter()
.map(|stop| {
let peniko_color = resolved_color_to_peniko(stop.color);
peniko::ColorStop {
offset: stop.offset,
color: peniko_color.into(),
}
})
.collect();
let gradient =
peniko::Gradient::new_linear(point_to_kurbo(self.start), point_to_kurbo(self.end))
.with_stops(&*peniko_stops);
peniko::Brush::Gradient(gradient)
}
}
#[derive(Debug, Clone)]
pub struct RadialGradient {
center0: Point,
radius0: f32,
center1: Point,
radius1: f32,
stops: Vec<ColorStop>,
}
impl RadialGradient {
#[must_use]
pub const fn new(x0: f32, y0: f32, r0: f32, x1: f32, y1: f32, r1: f32) -> Self {
Self {
center0: Point::new(x0, y0),
radius0: r0,
center1: Point::new(x1, y1),
radius1: r1,
stops: Vec::new(),
}
}
pub fn add_color_stop(&mut self, offset: f32, color: impl Into<ResolvedColor>) {
self.stops.push(ColorStop::new(offset, color));
}
#[must_use]
pub(crate) fn build(&self) -> peniko::Brush {
let peniko_stops: Vec<peniko::ColorStop> = self
.stops
.iter()
.map(|stop| {
let peniko_color = resolved_color_to_peniko(stop.color);
peniko::ColorStop {
offset: stop.offset,
color: peniko_color.into(),
}
})
.collect();
let gradient = peniko::Gradient::new_two_point_radial(
point_to_kurbo(self.center0),
self.radius0,
point_to_kurbo(self.center1),
self.radius1,
)
.with_stops(&*peniko_stops);
peniko::Brush::Gradient(gradient)
}
}
#[derive(Debug, Clone)]
pub struct ConicGradient {
center: Point,
start_angle: f32,
stops: Vec<ColorStop>,
}
impl ConicGradient {
#[must_use]
pub const fn new(start_angle: f32, x: f32, y: f32) -> Self {
Self {
center: Point::new(x, y),
start_angle,
stops: Vec::new(),
}
}
pub fn add_color_stop(&mut self, offset: f32, color: impl Into<ResolvedColor>) {
self.stops.push(ColorStop::new(offset, color));
}
#[must_use]
pub(crate) fn build(&self) -> peniko::Brush {
let peniko_stops: Vec<peniko::ColorStop> = self
.stops
.iter()
.map(|stop| {
let peniko_color = resolved_color_to_peniko(stop.color);
peniko::ColorStop {
offset: stop.offset,
color: peniko_color.into(),
}
})
.collect();
let gradient =
peniko::Gradient::new_sweep(point_to_kurbo(self.center), self.start_angle, 0.0)
.with_stops(&*peniko_stops);
peniko::Brush::Gradient(gradient)
}
}