tessera_components/
painter.rs1use std::{
7 io,
8 path::{Path, PathBuf},
9 sync::Arc,
10};
11
12use tessera_ui::{Asset, LoadState, Resource, Source};
13
14use crate::{
15 image::{ImageData, decode_raster},
16 image_vector::{ImageVectorData, decode_vector},
17};
18
19#[derive(Debug, Clone, PartialEq, Eq)]
24pub enum Painter {
25 Source(Resource<Painter>),
27 Vector(ImageVectorData),
29 Raster(ImageData),
31}
32
33impl From<ImageVectorData> for Painter {
34 fn from(data: ImageVectorData) -> Self {
35 Self::Vector(data)
36 }
37}
38
39impl From<ImageData> for Painter {
40 fn from(data: ImageData) -> Self {
41 Self::Raster(data)
42 }
43}
44
45macro_rules! painter_from_source {
46 ($($ty:ty),* $(,)?) => {$(
47 impl From<$ty> for Painter {
48 fn from(source: $ty) -> Self {
49 Self::Source(Resource::load(source, decode))
50 }
51 }
52 )*};
53}
54
55painter_from_source!(
56 Source,
57 Asset,
58 &str,
59 String,
60 &Path,
61 PathBuf,
62 &[u8],
63 Vec<u8>,
64 Arc<[u8]>
65);
66
67impl Painter {
68 pub(crate) fn resolve(self) -> Option<Self> {
69 match self {
70 Self::Source(resource) => match resource.get() {
71 LoadState::Ready(painter) => Some(painter),
72 LoadState::Loading | LoadState::Failed(_) => None,
73 },
74 painter => Some(painter),
75 }
76 }
77}
78
79fn decode(bytes: Arc<[u8]>) -> io::Result<Painter> {
80 decode_vector(&bytes)
81 .map(Painter::Vector)
82 .or_else(|vector| {
83 decode_raster(&bytes)
84 .map(Painter::Raster)
85 .map_err(|raster| {
86 io::Error::other(format!("not SVG ({vector}) or raster ({raster})"))
87 })
88 })
89}