1use alloc::sync::Arc;
18use alloc::vec::Vec;
19
20use crate::DrawSink;
21use crate::color::{AlphaColor, Srgb};
22use crate::kurbo::{Affine, BezPath, Rect};
23use crate::peniko::{BlendMode, Gradient};
24use vello_common::paint::PaintType;
25
26#[derive(Clone, Debug)]
28pub enum AtlasPaint {
29 Solid(AlphaColor<Srgb>),
31 Gradient(Gradient),
33}
34
35impl From<AlphaColor<Srgb>> for AtlasPaint {
36 fn from(c: AlphaColor<Srgb>) -> Self {
37 Self::Solid(c)
38 }
39}
40
41impl From<Gradient> for AtlasPaint {
42 fn from(g: Gradient) -> Self {
43 Self::Gradient(g)
44 }
45}
46
47impl From<AtlasPaint> for PaintType {
48 fn from(paint: AtlasPaint) -> Self {
49 match paint {
50 AtlasPaint::Solid(color) => Self::Solid(color),
51 AtlasPaint::Gradient(gradient) => Self::Gradient(gradient),
52 }
53 }
54}
55
56#[derive(Clone, Debug)]
62pub enum AtlasCommand {
63 SetTransform(Affine),
65 SetPaint(AtlasPaint),
67 SetPaintTransform(Affine),
69 FillPath(Arc<BezPath>),
71 FillRect(Rect),
73 PushClipLayer(Arc<BezPath>),
75 PushClipPath(Arc<BezPath>),
77 PushBlendLayer(BlendMode),
79 PopLayer,
81 PopClipPath,
83}
84
85pub struct AtlasCommandRecorder {
93 pub page_index: u32,
95 pub commands: Vec<AtlasCommand>,
97 pub(crate) width: u16,
99 pub(crate) height: u16,
101}
102
103impl AtlasCommandRecorder {
104 pub fn new(page_index: u32, width: u16, height: u16) -> Self {
110 Self {
111 page_index,
112 commands: Vec::new(),
113 width,
114 height,
115 }
116 }
117}
118
119impl DrawSink for AtlasCommandRecorder {
120 #[inline]
121 fn set_transform(&mut self, t: Affine) {
122 self.commands.push(AtlasCommand::SetTransform(t));
123 }
124
125 #[inline]
126 fn set_paint(&mut self, paint: AtlasPaint) {
127 self.commands.push(AtlasCommand::SetPaint(paint));
128 }
129
130 #[inline]
131 fn set_paint_transform(&mut self, t: Affine) {
132 self.commands.push(AtlasCommand::SetPaintTransform(t));
133 }
134
135 #[inline]
136 fn fill_path(&mut self, path: &BezPath) {
137 self.commands
138 .push(AtlasCommand::FillPath(Arc::new(path.clone())));
139 }
140
141 #[inline]
142 fn fill_rect(&mut self, rect: &Rect) {
143 self.commands.push(AtlasCommand::FillRect(*rect));
144 }
145
146 #[inline]
147 fn push_clip_layer(&mut self, clip: &BezPath) {
148 self.commands
149 .push(AtlasCommand::PushClipLayer(Arc::new(clip.clone())));
150 }
151
152 #[inline]
153 fn push_clip_path(&mut self, clip: &BezPath) {
154 self.commands
155 .push(AtlasCommand::PushClipPath(Arc::new(clip.clone())));
156 }
157
158 #[inline]
159 fn push_blend_layer(&mut self, blend_mode: BlendMode) {
160 self.commands.push(AtlasCommand::PushBlendLayer(blend_mode));
161 }
162
163 #[inline]
164 fn pop_layer(&mut self) {
165 self.commands.push(AtlasCommand::PopLayer);
166 }
167
168 #[inline]
169 fn pop_clip_path(&mut self) {
170 self.commands.push(AtlasCommand::PopClipPath);
171 }
172
173 #[inline]
174 fn width(&self) -> u16 {
175 self.width
176 }
177
178 #[inline]
179 fn height(&self) -> u16 {
180 self.height
181 }
182}
183
184impl core::fmt::Debug for AtlasCommandRecorder {
185 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
186 f.debug_struct("AtlasCommandRecorder")
187 .field("page_index", &self.page_index)
188 .field("commands", &self.commands.len())
189 .field("width", &self.width)
190 .field("height", &self.height)
191 .finish()
192 }
193}