typst_library/visualize/
paint.rs

1use std::fmt::{self, Debug, Formatter};
2
3use ecow::EcoString;
4
5use crate::foundations::{cast, Repr, Smart};
6use crate::visualize::{Color, Gradient, RelativeTo, Tiling};
7
8/// How a fill or stroke should be painted.
9#[derive(Clone, Eq, PartialEq, Hash)]
10pub enum Paint {
11    /// A solid color.
12    Solid(Color),
13    /// A gradient.
14    Gradient(Gradient),
15    /// A tiling.
16    Tiling(Tiling),
17}
18
19impl Paint {
20    /// Unwraps a solid color used for text rendering.
21    pub fn unwrap_solid(&self) -> Color {
22        match self {
23            Self::Solid(color) => *color,
24            Self::Gradient(_) | Self::Tiling(_) => panic!("expected solid color"),
25        }
26    }
27
28    /// Gets the relative coordinate system for this paint.
29    pub fn relative(&self) -> Smart<RelativeTo> {
30        match self {
31            Self::Solid(_) => Smart::Auto,
32            Self::Gradient(gradient) => gradient.relative(),
33            Self::Tiling(tiling) => tiling.relative(),
34        }
35    }
36
37    /// Turns this paint into a paint for a text decoration.
38    ///
39    /// If this paint is a gradient, it will be converted to a gradient with
40    /// relative set to [`RelativeTo::Parent`].
41    pub fn as_decoration(&self) -> Self {
42        match self {
43            Self::Solid(color) => Self::Solid(*color),
44            Self::Gradient(gradient) => {
45                Self::Gradient(gradient.clone().with_relative(RelativeTo::Parent))
46            }
47            Self::Tiling(tiling) => {
48                Self::Tiling(tiling.clone().with_relative(RelativeTo::Parent))
49            }
50        }
51    }
52}
53
54impl Debug for Paint {
55    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
56        match self {
57            Self::Solid(v) => v.fmt(f),
58            Self::Gradient(v) => v.fmt(f),
59            Self::Tiling(v) => v.fmt(f),
60        }
61    }
62}
63
64impl From<Tiling> for Paint {
65    fn from(tiling: Tiling) -> Self {
66        Self::Tiling(tiling)
67    }
68}
69
70impl Repr for Paint {
71    fn repr(&self) -> EcoString {
72        match self {
73            Self::Solid(color) => color.repr(),
74            Self::Gradient(gradient) => gradient.repr(),
75            Self::Tiling(tiling) => tiling.repr(),
76        }
77    }
78}
79
80impl<T: Into<Color>> From<T> for Paint {
81    fn from(t: T) -> Self {
82        Self::Solid(t.into())
83    }
84}
85
86impl From<Gradient> for Paint {
87    fn from(gradient: Gradient) -> Self {
88        Self::Gradient(gradient)
89    }
90}
91
92cast! {
93    Paint,
94    self => match self {
95        Self::Solid(color) => color.into_value(),
96        Self::Gradient(gradient) => gradient.into_value(),
97        Self::Tiling(tiling) => tiling.into_value(),
98    },
99    color: Color => Self::Solid(color),
100    gradient: Gradient => Self::Gradient(gradient),
101    tiling: Tiling => Self::Tiling(tiling),
102}