use waterui_color::ResolvedColor;
use vello::{kurbo, peniko};
use super::gradient::{ConicGradient, LinearGradient, RadialGradient};
use super::text::FontSpec;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
pub enum FillRule {
#[default]
NonZero,
EvenOdd,
}
impl FillRule {
pub(crate) const fn to_peniko(self) -> peniko::Fill {
match self {
Self::NonZero => peniko::Fill::NonZero,
Self::EvenOdd => peniko::Fill::EvenOdd,
}
}
}
#[derive(Debug, Clone)]
pub enum FillStyle {
Color(ResolvedColor),
LinearGradient(LinearGradient),
RadialGradient(RadialGradient),
ConicGradient(ConicGradient),
}
impl<T> From<T> for FillStyle
where
T: Into<ResolvedColor>,
{
fn from(color: T) -> Self {
Self::Color(color.into())
}
}
impl From<LinearGradient> for FillStyle {
fn from(gradient: LinearGradient) -> Self {
Self::LinearGradient(gradient)
}
}
impl From<RadialGradient> for FillStyle {
fn from(gradient: RadialGradient) -> Self {
Self::RadialGradient(gradient)
}
}
impl From<ConicGradient> for FillStyle {
fn from(gradient: ConicGradient) -> Self {
Self::ConicGradient(gradient)
}
}
#[derive(Debug, Clone)]
pub enum StrokeStyle {
Color(ResolvedColor),
LinearGradient(LinearGradient),
RadialGradient(RadialGradient),
ConicGradient(ConicGradient),
}
impl<T> From<T> for StrokeStyle
where
T: Into<ResolvedColor>,
{
fn from(color: T) -> Self {
Self::Color(color.into())
}
}
impl From<LinearGradient> for StrokeStyle {
fn from(gradient: LinearGradient) -> Self {
Self::LinearGradient(gradient)
}
}
impl From<RadialGradient> for StrokeStyle {
fn from(gradient: RadialGradient) -> Self {
Self::RadialGradient(gradient)
}
}
impl From<ConicGradient> for StrokeStyle {
fn from(gradient: ConicGradient) -> Self {
Self::ConicGradient(gradient)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
pub enum LineCap {
#[default]
Butt,
Round,
Square,
}
impl LineCap {
pub(crate) const fn to_kurbo(self) -> kurbo::Cap {
match self {
Self::Butt => kurbo::Cap::Butt,
Self::Round => kurbo::Cap::Round,
Self::Square => kurbo::Cap::Square,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
pub enum LineJoin {
#[default]
Miter,
Round,
Bevel,
}
impl LineJoin {
pub(crate) const fn to_kurbo(self) -> kurbo::Join {
match self {
Self::Miter => kurbo::Join::Miter,
Self::Round => kurbo::Join::Round,
Self::Bevel => kurbo::Join::Bevel,
}
}
}
#[derive(Debug, Clone)]
pub(crate) struct DrawingState {
pub(crate) transform: kurbo::Affine,
pub(crate) fill_style: FillStyle,
pub(crate) stroke_style: StrokeStyle,
pub(crate) line_width: f32,
pub(crate) line_cap: LineCap,
pub(crate) line_join: LineJoin,
pub(crate) miter_limit: f32,
pub(crate) line_dash: Vec<f32>,
pub(crate) line_dash_offset: f32,
pub(crate) global_alpha: f32,
pub(crate) blend_mode: peniko::BlendMode,
pub(crate) font: FontSpec,
pub(crate) shadow_blur: f32,
pub(crate) shadow_color: ResolvedColor,
pub(crate) shadow_offset_x: f32,
pub(crate) shadow_offset_y: f32,
pub(crate) fill_rule: peniko::Fill,
}
impl Default for DrawingState {
fn default() -> Self {
Self {
transform: kurbo::Affine::IDENTITY,
fill_style: FillStyle::Color(ResolvedColor::from_srgb(waterui_color::Srgb::BLACK)),
stroke_style: StrokeStyle::Color(ResolvedColor::from_srgb(waterui_color::Srgb::BLACK)),
line_width: 1.0,
line_cap: LineCap::default(),
line_join: LineJoin::default(),
miter_limit: 10.0,
line_dash: Vec::new(),
line_dash_offset: 0.0,
global_alpha: 1.0,
blend_mode: peniko::BlendMode::default(),
font: FontSpec::default(),
shadow_blur: 0.0,
shadow_color: ResolvedColor::from_srgb(waterui_color::Srgb::BLACK).with_opacity(0.0),
shadow_offset_x: 0.0,
shadow_offset_y: 0.0,
fill_rule: peniko::Fill::NonZero, }
}
}
impl DrawingState {
#[must_use]
pub(crate) fn new() -> Self {
Self::default()
}
#[must_use]
pub(crate) fn build_stroke(&self) -> kurbo::Stroke {
let mut stroke = kurbo::Stroke::new(f64::from(self.line_width))
.with_caps(self.line_cap.to_kurbo())
.with_join(self.line_join.to_kurbo())
.with_miter_limit(f64::from(self.miter_limit));
if !self.line_dash.is_empty() {
let dashes: Vec<f64> = self.line_dash.iter().map(|&d| f64::from(d)).collect();
stroke = stroke.with_dashes(f64::from(self.line_dash_offset), dashes);
}
stroke
}
}