xref: /aosp_15_r20/external/skia/third_party/vello/src/encoding.rs (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker // Copyright 2023 Google LLC
2*c8dee2aaSAndroid Build Coastguard Worker //
3*c8dee2aaSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*c8dee2aaSAndroid Build Coastguard Worker // found in the LICENSE file.
5*c8dee2aaSAndroid Build Coastguard Worker 
6*c8dee2aaSAndroid Build Coastguard Worker use crate::ffi;
7*c8dee2aaSAndroid Build Coastguard Worker use {
8*c8dee2aaSAndroid Build Coastguard Worker     peniko::{
9*c8dee2aaSAndroid Build Coastguard Worker         kurbo::{Affine, Cap, Join, PathEl, Point, Stroke},
10*c8dee2aaSAndroid Build Coastguard Worker         Brush, Color, Fill, Mix,
11*c8dee2aaSAndroid Build Coastguard Worker     },
12*c8dee2aaSAndroid Build Coastguard Worker     std::pin::Pin,
13*c8dee2aaSAndroid Build Coastguard Worker     vello_encoding::{
14*c8dee2aaSAndroid Build Coastguard Worker         BumpEstimator, Encoding as VelloEncoding, PathEncoder, RenderConfig, Transform,
15*c8dee2aaSAndroid Build Coastguard Worker     },
16*c8dee2aaSAndroid Build Coastguard Worker };
17*c8dee2aaSAndroid Build Coastguard Worker 
18*c8dee2aaSAndroid Build Coastguard Worker pub(crate) struct Encoding {
19*c8dee2aaSAndroid Build Coastguard Worker     encoding: VelloEncoding,
20*c8dee2aaSAndroid Build Coastguard Worker     estimator: BumpEstimator,
21*c8dee2aaSAndroid Build Coastguard Worker }
22*c8dee2aaSAndroid Build Coastguard Worker 
new_encoding() -> Box<Encoding>23*c8dee2aaSAndroid Build Coastguard Worker pub(crate) fn new_encoding() -> Box<Encoding> {
24*c8dee2aaSAndroid Build Coastguard Worker     Box::new(Encoding::new())
25*c8dee2aaSAndroid Build Coastguard Worker }
26*c8dee2aaSAndroid Build Coastguard Worker 
27*c8dee2aaSAndroid Build Coastguard Worker impl Encoding {
new() -> Encoding28*c8dee2aaSAndroid Build Coastguard Worker     fn new() -> Encoding {
29*c8dee2aaSAndroid Build Coastguard Worker         // An encoding blob that doesn't represent a scene fragment (i.e. a reused blob that is
30*c8dee2aaSAndroid Build Coastguard Worker         // appended to a root encoding), then we need to initialize the transform and linewidth
31*c8dee2aaSAndroid Build Coastguard Worker         // streams with first entries (an identity transform and -1 linewidth value). Resetting
32*c8dee2aaSAndroid Build Coastguard Worker         // the encoding as non-fragment achieves this.
33*c8dee2aaSAndroid Build Coastguard Worker         let mut encoding = VelloEncoding::new();
34*c8dee2aaSAndroid Build Coastguard Worker         encoding.reset();
35*c8dee2aaSAndroid Build Coastguard Worker         Encoding { encoding, estimator: BumpEstimator::new(), }
36*c8dee2aaSAndroid Build Coastguard Worker     }
37*c8dee2aaSAndroid Build Coastguard Worker 
is_empty(&self) -> bool38*c8dee2aaSAndroid Build Coastguard Worker     pub fn is_empty(&self) -> bool {
39*c8dee2aaSAndroid Build Coastguard Worker         self.encoding.is_empty()
40*c8dee2aaSAndroid Build Coastguard Worker     }
41*c8dee2aaSAndroid Build Coastguard Worker 
reset(&mut self)42*c8dee2aaSAndroid Build Coastguard Worker     pub fn reset(&mut self) {
43*c8dee2aaSAndroid Build Coastguard Worker         self.encoding.reset();
44*c8dee2aaSAndroid Build Coastguard Worker         self.estimator.reset();
45*c8dee2aaSAndroid Build Coastguard Worker     }
46*c8dee2aaSAndroid Build Coastguard Worker 
fill( &mut self, style: ffi::Fill, transform: ffi::Affine, brush: &ffi::Brush, path_iter: Pin<&mut ffi::PathIterator>, )47*c8dee2aaSAndroid Build Coastguard Worker     pub fn fill(
48*c8dee2aaSAndroid Build Coastguard Worker         &mut self,
49*c8dee2aaSAndroid Build Coastguard Worker         style: ffi::Fill,
50*c8dee2aaSAndroid Build Coastguard Worker         transform: ffi::Affine,
51*c8dee2aaSAndroid Build Coastguard Worker         brush: &ffi::Brush,
52*c8dee2aaSAndroid Build Coastguard Worker         path_iter: Pin<&mut ffi::PathIterator>,
53*c8dee2aaSAndroid Build Coastguard Worker     ) {
54*c8dee2aaSAndroid Build Coastguard Worker         let t = Transform::from_kurbo(&transform.into());
55*c8dee2aaSAndroid Build Coastguard Worker         self.encoding.encode_transform(t);
56*c8dee2aaSAndroid Build Coastguard Worker         self.encoding.encode_fill_style(style.into());
57*c8dee2aaSAndroid Build Coastguard Worker         if self.encode_path(path_iter, &t, None) {
58*c8dee2aaSAndroid Build Coastguard Worker             self.encoding.encode_brush(&Brush::from(brush), 1.0)
59*c8dee2aaSAndroid Build Coastguard Worker         }
60*c8dee2aaSAndroid Build Coastguard Worker     }
61*c8dee2aaSAndroid Build Coastguard Worker 
stroke( &mut self, style: &ffi::Stroke, transform: ffi::Affine, brush: &ffi::Brush, path_iter: Pin<&mut ffi::PathIterator>, )62*c8dee2aaSAndroid Build Coastguard Worker     pub fn stroke(
63*c8dee2aaSAndroid Build Coastguard Worker         &mut self,
64*c8dee2aaSAndroid Build Coastguard Worker         style: &ffi::Stroke,
65*c8dee2aaSAndroid Build Coastguard Worker         transform: ffi::Affine,
66*c8dee2aaSAndroid Build Coastguard Worker         brush: &ffi::Brush,
67*c8dee2aaSAndroid Build Coastguard Worker         path_iter: Pin<&mut ffi::PathIterator>,
68*c8dee2aaSAndroid Build Coastguard Worker     ) {
69*c8dee2aaSAndroid Build Coastguard Worker         let t = Transform::from_kurbo(&transform.into());
70*c8dee2aaSAndroid Build Coastguard Worker         self.encoding.encode_transform(t);
71*c8dee2aaSAndroid Build Coastguard Worker 
72*c8dee2aaSAndroid Build Coastguard Worker         // TODO: process any dash pattern here using kurbo's dash expander unless Graphite
73*c8dee2aaSAndroid Build Coastguard Worker         // handles dashing already.
74*c8dee2aaSAndroid Build Coastguard Worker         let stroke = style.into();
75*c8dee2aaSAndroid Build Coastguard Worker         self.encoding.encode_stroke_style(&stroke);
76*c8dee2aaSAndroid Build Coastguard Worker         if self.encode_path(path_iter, &t, Some(&stroke)) {
77*c8dee2aaSAndroid Build Coastguard Worker             self.encoding.encode_brush(&Brush::from(brush), 1.0);
78*c8dee2aaSAndroid Build Coastguard Worker         }
79*c8dee2aaSAndroid Build Coastguard Worker     }
80*c8dee2aaSAndroid Build Coastguard Worker 
begin_clip(&mut self, transform: ffi::Affine, path_iter: Pin<&mut ffi::PathIterator>)81*c8dee2aaSAndroid Build Coastguard Worker     pub fn begin_clip(&mut self, transform: ffi::Affine, path_iter: Pin<&mut ffi::PathIterator>) {
82*c8dee2aaSAndroid Build Coastguard Worker         let t = Transform::from_kurbo(&transform.into());
83*c8dee2aaSAndroid Build Coastguard Worker         self.encoding.encode_transform(t);
84*c8dee2aaSAndroid Build Coastguard Worker         self.encoding.encode_fill_style(Fill::NonZero);
85*c8dee2aaSAndroid Build Coastguard Worker         self.encode_path(path_iter, &t, None);
86*c8dee2aaSAndroid Build Coastguard Worker         self.encoding.encode_begin_clip(Mix::Clip.into(), /*alpha=*/ 1.0);
87*c8dee2aaSAndroid Build Coastguard Worker     }
88*c8dee2aaSAndroid Build Coastguard Worker 
end_clip(&mut self)89*c8dee2aaSAndroid Build Coastguard Worker     pub fn end_clip(&mut self) {
90*c8dee2aaSAndroid Build Coastguard Worker         self.encoding.encode_end_clip();
91*c8dee2aaSAndroid Build Coastguard Worker     }
92*c8dee2aaSAndroid Build Coastguard Worker 
append(&mut self, other: &Encoding)93*c8dee2aaSAndroid Build Coastguard Worker     pub fn append(&mut self, other: &Encoding) {
94*c8dee2aaSAndroid Build Coastguard Worker         self.encoding.append(&other.encoding, &None);
95*c8dee2aaSAndroid Build Coastguard Worker         self.estimator.append(&other.estimator, None);
96*c8dee2aaSAndroid Build Coastguard Worker     }
97*c8dee2aaSAndroid Build Coastguard Worker 
prepare_render( &self, width: u32, height: u32, background: &ffi::Color, ) -> Box<RenderConfiguration>98*c8dee2aaSAndroid Build Coastguard Worker     pub fn prepare_render(
99*c8dee2aaSAndroid Build Coastguard Worker         &self,
100*c8dee2aaSAndroid Build Coastguard Worker         width: u32,
101*c8dee2aaSAndroid Build Coastguard Worker         height: u32,
102*c8dee2aaSAndroid Build Coastguard Worker         background: &ffi::Color,
103*c8dee2aaSAndroid Build Coastguard Worker     ) -> Box<RenderConfiguration> {
104*c8dee2aaSAndroid Build Coastguard Worker         let mut packed_scene = Vec::new();
105*c8dee2aaSAndroid Build Coastguard Worker         let layout = vello_encoding::resolve_solid_paths_only(&self.encoding, &mut packed_scene);
106*c8dee2aaSAndroid Build Coastguard Worker         let mut config = RenderConfig::new(&layout, width, height, &background.into());
107*c8dee2aaSAndroid Build Coastguard Worker 
108*c8dee2aaSAndroid Build Coastguard Worker         let bump_estimate = self.estimator.tally(None);
109*c8dee2aaSAndroid Build Coastguard Worker         //println!("bump: {bump_estimate}");
110*c8dee2aaSAndroid Build Coastguard Worker         config.buffer_sizes.bin_data = bump_estimate.binning;
111*c8dee2aaSAndroid Build Coastguard Worker         config.buffer_sizes.seg_counts = bump_estimate.seg_counts;
112*c8dee2aaSAndroid Build Coastguard Worker         config.buffer_sizes.segments = bump_estimate.segments;
113*c8dee2aaSAndroid Build Coastguard Worker         config.buffer_sizes.lines = bump_estimate.lines;
114*c8dee2aaSAndroid Build Coastguard Worker         config.gpu.binning_size = bump_estimate.binning.len();
115*c8dee2aaSAndroid Build Coastguard Worker         config.gpu.seg_counts_size = bump_estimate.seg_counts.len();
116*c8dee2aaSAndroid Build Coastguard Worker         config.gpu.segments_size = bump_estimate.segments.len();
117*c8dee2aaSAndroid Build Coastguard Worker         config.gpu.lines_size = bump_estimate.lines.len();
118*c8dee2aaSAndroid Build Coastguard Worker 
119*c8dee2aaSAndroid Build Coastguard Worker         Box::new(RenderConfiguration {
120*c8dee2aaSAndroid Build Coastguard Worker             packed_scene,
121*c8dee2aaSAndroid Build Coastguard Worker             config,
122*c8dee2aaSAndroid Build Coastguard Worker         })
123*c8dee2aaSAndroid Build Coastguard Worker     }
124*c8dee2aaSAndroid Build Coastguard Worker 
encode_path( &mut self, iter: Pin<&mut ffi::PathIterator>, transform: &Transform, stroke: Option<&Stroke>, ) -> bool125*c8dee2aaSAndroid Build Coastguard Worker     fn encode_path(
126*c8dee2aaSAndroid Build Coastguard Worker         &mut self,
127*c8dee2aaSAndroid Build Coastguard Worker         iter: Pin<&mut ffi::PathIterator>,
128*c8dee2aaSAndroid Build Coastguard Worker         transform: &Transform,
129*c8dee2aaSAndroid Build Coastguard Worker         stroke: Option<&Stroke>,
130*c8dee2aaSAndroid Build Coastguard Worker     ) -> bool {
131*c8dee2aaSAndroid Build Coastguard Worker         let mut encoder = self.encoding.encode_path(/*is_fill=*/ stroke.is_none());
132*c8dee2aaSAndroid Build Coastguard Worker 
133*c8dee2aaSAndroid Build Coastguard Worker         // Wrap the input iterator inside a custom iterator, so that the path gets
134*c8dee2aaSAndroid Build Coastguard Worker         // encoded as the estimator runs through it.
135*c8dee2aaSAndroid Build Coastguard Worker         let path = IterablePathEncoder { iter, encoder: &mut encoder };
136*c8dee2aaSAndroid Build Coastguard Worker         self.estimator.count_path(path, transform, stroke);
137*c8dee2aaSAndroid Build Coastguard Worker         encoder.finish(/*insert_path_marker=*/ true) != 0
138*c8dee2aaSAndroid Build Coastguard Worker     }
139*c8dee2aaSAndroid Build Coastguard Worker }
140*c8dee2aaSAndroid Build Coastguard Worker 
141*c8dee2aaSAndroid Build Coastguard Worker // This is path element iterator that encodes path elements as it gets polled.
142*c8dee2aaSAndroid Build Coastguard Worker struct IterablePathEncoder<'a, 'b> {
143*c8dee2aaSAndroid Build Coastguard Worker     iter: Pin<&'a mut ffi::PathIterator>,
144*c8dee2aaSAndroid Build Coastguard Worker     encoder: &'a mut PathEncoder<'b>,
145*c8dee2aaSAndroid Build Coastguard Worker }
146*c8dee2aaSAndroid Build Coastguard Worker 
147*c8dee2aaSAndroid Build Coastguard Worker impl Iterator for IterablePathEncoder<'_, '_> {
148*c8dee2aaSAndroid Build Coastguard Worker     type Item = PathEl;
149*c8dee2aaSAndroid Build Coastguard Worker 
next(&mut self) -> Option<Self::Item>150*c8dee2aaSAndroid Build Coastguard Worker     fn next(&mut self) -> Option<Self::Item> {
151*c8dee2aaSAndroid Build Coastguard Worker         let mut path_el = ffi::PathElement::default();
152*c8dee2aaSAndroid Build Coastguard Worker         if !unsafe { self.iter.as_mut().next_element(&mut path_el) } {
153*c8dee2aaSAndroid Build Coastguard Worker             return None;
154*c8dee2aaSAndroid Build Coastguard Worker         }
155*c8dee2aaSAndroid Build Coastguard Worker         Some(match path_el.verb {
156*c8dee2aaSAndroid Build Coastguard Worker             ffi::PathVerb::MoveTo => {
157*c8dee2aaSAndroid Build Coastguard Worker                 let p = &path_el.points[0];
158*c8dee2aaSAndroid Build Coastguard Worker                 self.encoder.move_to(p.x, p.y);
159*c8dee2aaSAndroid Build Coastguard Worker                 PathEl::MoveTo(p.into())
160*c8dee2aaSAndroid Build Coastguard Worker             }
161*c8dee2aaSAndroid Build Coastguard Worker             ffi::PathVerb::LineTo => {
162*c8dee2aaSAndroid Build Coastguard Worker                 let p = &path_el.points[1];
163*c8dee2aaSAndroid Build Coastguard Worker                 self.encoder.line_to(p.x, p.y);
164*c8dee2aaSAndroid Build Coastguard Worker                 PathEl::LineTo(p.into())
165*c8dee2aaSAndroid Build Coastguard Worker             }
166*c8dee2aaSAndroid Build Coastguard Worker             ffi::PathVerb::QuadTo => {
167*c8dee2aaSAndroid Build Coastguard Worker                 let p0 = &path_el.points[1];
168*c8dee2aaSAndroid Build Coastguard Worker                 let p1 = &path_el.points[2];
169*c8dee2aaSAndroid Build Coastguard Worker                 self.encoder.quad_to(p0.x, p0.y, p1.x, p1.y);
170*c8dee2aaSAndroid Build Coastguard Worker                 PathEl::QuadTo(p0.into(), p1.into())
171*c8dee2aaSAndroid Build Coastguard Worker             }
172*c8dee2aaSAndroid Build Coastguard Worker             ffi::PathVerb::CurveTo => {
173*c8dee2aaSAndroid Build Coastguard Worker                 let p0 = &path_el.points[1];
174*c8dee2aaSAndroid Build Coastguard Worker                 let p1 = &path_el.points[2];
175*c8dee2aaSAndroid Build Coastguard Worker                 let p2 = &path_el.points[3];
176*c8dee2aaSAndroid Build Coastguard Worker                 self.encoder.cubic_to(p0.x, p0.y, p1.x, p1.y, p2.x, p2.y);
177*c8dee2aaSAndroid Build Coastguard Worker                 PathEl::CurveTo(p0.into(), p1.into(), p2.into())
178*c8dee2aaSAndroid Build Coastguard Worker             }
179*c8dee2aaSAndroid Build Coastguard Worker             ffi::PathVerb::Close => {
180*c8dee2aaSAndroid Build Coastguard Worker                 self.encoder.close();
181*c8dee2aaSAndroid Build Coastguard Worker                 PathEl::ClosePath
182*c8dee2aaSAndroid Build Coastguard Worker             }
183*c8dee2aaSAndroid Build Coastguard Worker             _ => panic!("invalid path verb"),
184*c8dee2aaSAndroid Build Coastguard Worker         })
185*c8dee2aaSAndroid Build Coastguard Worker     }
186*c8dee2aaSAndroid Build Coastguard Worker }
187*c8dee2aaSAndroid Build Coastguard Worker 
188*c8dee2aaSAndroid Build Coastguard Worker pub(crate) struct RenderConfiguration {
189*c8dee2aaSAndroid Build Coastguard Worker     packed_scene: Vec<u8>,
190*c8dee2aaSAndroid Build Coastguard Worker     config: RenderConfig,
191*c8dee2aaSAndroid Build Coastguard Worker }
192*c8dee2aaSAndroid Build Coastguard Worker 
193*c8dee2aaSAndroid Build Coastguard Worker impl RenderConfiguration {
config_uniform_buffer_size(self: &RenderConfiguration) -> usize194*c8dee2aaSAndroid Build Coastguard Worker     pub fn config_uniform_buffer_size(self: &RenderConfiguration) -> usize {
195*c8dee2aaSAndroid Build Coastguard Worker         std::mem::size_of::<vello_encoding::ConfigUniform>()
196*c8dee2aaSAndroid Build Coastguard Worker     }
197*c8dee2aaSAndroid Build Coastguard Worker 
scene_buffer_size(self: &RenderConfiguration) -> usize198*c8dee2aaSAndroid Build Coastguard Worker     pub fn scene_buffer_size(self: &RenderConfiguration) -> usize {
199*c8dee2aaSAndroid Build Coastguard Worker         self.packed_scene.len()
200*c8dee2aaSAndroid Build Coastguard Worker     }
201*c8dee2aaSAndroid Build Coastguard Worker 
write_config_uniform_buffer(self: &RenderConfiguration, out_buffer: &mut [u8]) -> bool202*c8dee2aaSAndroid Build Coastguard Worker     pub fn write_config_uniform_buffer(self: &RenderConfiguration, out_buffer: &mut [u8]) -> bool {
203*c8dee2aaSAndroid Build Coastguard Worker         let bytes = bytemuck::bytes_of(&self.config.gpu);
204*c8dee2aaSAndroid Build Coastguard Worker         if out_buffer.len() < bytes.len() {
205*c8dee2aaSAndroid Build Coastguard Worker             return false;
206*c8dee2aaSAndroid Build Coastguard Worker         }
207*c8dee2aaSAndroid Build Coastguard Worker         out_buffer.copy_from_slice(bytes);
208*c8dee2aaSAndroid Build Coastguard Worker         true
209*c8dee2aaSAndroid Build Coastguard Worker     }
210*c8dee2aaSAndroid Build Coastguard Worker 
write_scene_buffer(self: &RenderConfiguration, out_buffer: &mut [u8]) -> bool211*c8dee2aaSAndroid Build Coastguard Worker     pub fn write_scene_buffer(self: &RenderConfiguration, out_buffer: &mut [u8]) -> bool {
212*c8dee2aaSAndroid Build Coastguard Worker         if out_buffer.len() < self.packed_scene.len() {
213*c8dee2aaSAndroid Build Coastguard Worker             return false;
214*c8dee2aaSAndroid Build Coastguard Worker         }
215*c8dee2aaSAndroid Build Coastguard Worker         out_buffer.copy_from_slice(&self.packed_scene);
216*c8dee2aaSAndroid Build Coastguard Worker         true
217*c8dee2aaSAndroid Build Coastguard Worker     }
218*c8dee2aaSAndroid Build Coastguard Worker 
workgroup_counts(self: &RenderConfiguration) -> ffi::DispatchInfo219*c8dee2aaSAndroid Build Coastguard Worker     pub fn workgroup_counts(self: &RenderConfiguration) -> ffi::DispatchInfo {
220*c8dee2aaSAndroid Build Coastguard Worker         (&self.config.workgroup_counts).into()
221*c8dee2aaSAndroid Build Coastguard Worker     }
222*c8dee2aaSAndroid Build Coastguard Worker 
buffer_sizes(self: &RenderConfiguration) -> ffi::BufferSizes223*c8dee2aaSAndroid Build Coastguard Worker     pub fn buffer_sizes(self: &RenderConfiguration) -> ffi::BufferSizes {
224*c8dee2aaSAndroid Build Coastguard Worker         (&self.config.buffer_sizes).into()
225*c8dee2aaSAndroid Build Coastguard Worker     }
226*c8dee2aaSAndroid Build Coastguard Worker }
227*c8dee2aaSAndroid Build Coastguard Worker 
228*c8dee2aaSAndroid Build Coastguard Worker impl Iterator for Pin<&mut ffi::PathIterator> {
229*c8dee2aaSAndroid Build Coastguard Worker     type Item = PathEl;
230*c8dee2aaSAndroid Build Coastguard Worker 
next(&mut self) -> Option<PathEl>231*c8dee2aaSAndroid Build Coastguard Worker     fn next(&mut self) -> Option<PathEl> {
232*c8dee2aaSAndroid Build Coastguard Worker         let mut path_el = ffi::PathElement::default();
233*c8dee2aaSAndroid Build Coastguard Worker         if !unsafe { self.as_mut().next_element(&mut path_el) } {
234*c8dee2aaSAndroid Build Coastguard Worker             return None;
235*c8dee2aaSAndroid Build Coastguard Worker         }
236*c8dee2aaSAndroid Build Coastguard Worker         Some(match path_el.verb {
237*c8dee2aaSAndroid Build Coastguard Worker             ffi::PathVerb::MoveTo => {
238*c8dee2aaSAndroid Build Coastguard Worker                 let p = &path_el.points[0];
239*c8dee2aaSAndroid Build Coastguard Worker                 PathEl::MoveTo(p.into())
240*c8dee2aaSAndroid Build Coastguard Worker             }
241*c8dee2aaSAndroid Build Coastguard Worker             ffi::PathVerb::LineTo => {
242*c8dee2aaSAndroid Build Coastguard Worker                 let p = &path_el.points[1];
243*c8dee2aaSAndroid Build Coastguard Worker                 PathEl::LineTo(p.into())
244*c8dee2aaSAndroid Build Coastguard Worker             }
245*c8dee2aaSAndroid Build Coastguard Worker             ffi::PathVerb::QuadTo => {
246*c8dee2aaSAndroid Build Coastguard Worker                 let p0 = &path_el.points[1];
247*c8dee2aaSAndroid Build Coastguard Worker                 let p1 = &path_el.points[2];
248*c8dee2aaSAndroid Build Coastguard Worker                 PathEl::QuadTo(p0.into(), p1.into())
249*c8dee2aaSAndroid Build Coastguard Worker             }
250*c8dee2aaSAndroid Build Coastguard Worker             ffi::PathVerb::CurveTo => {
251*c8dee2aaSAndroid Build Coastguard Worker                 let p0 = &path_el.points[1];
252*c8dee2aaSAndroid Build Coastguard Worker                 let p1 = &path_el.points[2];
253*c8dee2aaSAndroid Build Coastguard Worker                 let p2 = &path_el.points[3];
254*c8dee2aaSAndroid Build Coastguard Worker                 PathEl::CurveTo(p0.into(), p1.into(), p2.into())
255*c8dee2aaSAndroid Build Coastguard Worker             }
256*c8dee2aaSAndroid Build Coastguard Worker             ffi::PathVerb::Close => PathEl::ClosePath,
257*c8dee2aaSAndroid Build Coastguard Worker             _ => panic!("invalid path verb"),
258*c8dee2aaSAndroid Build Coastguard Worker         })
259*c8dee2aaSAndroid Build Coastguard Worker     }
260*c8dee2aaSAndroid Build Coastguard Worker }
261*c8dee2aaSAndroid Build Coastguard Worker 
262*c8dee2aaSAndroid Build Coastguard Worker impl From<&ffi::Point> for Point {
from(src: &ffi::Point) -> Self263*c8dee2aaSAndroid Build Coastguard Worker     fn from(src: &ffi::Point) -> Self {
264*c8dee2aaSAndroid Build Coastguard Worker         Self::new(src.x.into(), src.y.into())
265*c8dee2aaSAndroid Build Coastguard Worker     }
266*c8dee2aaSAndroid Build Coastguard Worker }
267*c8dee2aaSAndroid Build Coastguard Worker 
268*c8dee2aaSAndroid Build Coastguard Worker impl Default for ffi::PathVerb {
default() -> Self269*c8dee2aaSAndroid Build Coastguard Worker     fn default() -> Self {
270*c8dee2aaSAndroid Build Coastguard Worker         Self::MoveTo
271*c8dee2aaSAndroid Build Coastguard Worker     }
272*c8dee2aaSAndroid Build Coastguard Worker }
273*c8dee2aaSAndroid Build Coastguard Worker 
274*c8dee2aaSAndroid Build Coastguard Worker impl From<ffi::Affine> for Affine {
from(src: ffi::Affine) -> Self275*c8dee2aaSAndroid Build Coastguard Worker     fn from(src: ffi::Affine) -> Self {
276*c8dee2aaSAndroid Build Coastguard Worker         Self::new([
277*c8dee2aaSAndroid Build Coastguard Worker             src.matrix[0] as f64,
278*c8dee2aaSAndroid Build Coastguard Worker             src.matrix[1] as f64,
279*c8dee2aaSAndroid Build Coastguard Worker             src.matrix[2] as f64,
280*c8dee2aaSAndroid Build Coastguard Worker             src.matrix[3] as f64,
281*c8dee2aaSAndroid Build Coastguard Worker             src.matrix[4] as f64,
282*c8dee2aaSAndroid Build Coastguard Worker             src.matrix[5] as f64,
283*c8dee2aaSAndroid Build Coastguard Worker         ])
284*c8dee2aaSAndroid Build Coastguard Worker     }
285*c8dee2aaSAndroid Build Coastguard Worker }
286*c8dee2aaSAndroid Build Coastguard Worker 
287*c8dee2aaSAndroid Build Coastguard Worker impl From<&ffi::Color> for Color {
from(src: &ffi::Color) -> Self288*c8dee2aaSAndroid Build Coastguard Worker     fn from(src: &ffi::Color) -> Self {
289*c8dee2aaSAndroid Build Coastguard Worker         Self {
290*c8dee2aaSAndroid Build Coastguard Worker             r: src.r,
291*c8dee2aaSAndroid Build Coastguard Worker             g: src.g,
292*c8dee2aaSAndroid Build Coastguard Worker             b: src.b,
293*c8dee2aaSAndroid Build Coastguard Worker             a: src.a,
294*c8dee2aaSAndroid Build Coastguard Worker         }
295*c8dee2aaSAndroid Build Coastguard Worker     }
296*c8dee2aaSAndroid Build Coastguard Worker }
297*c8dee2aaSAndroid Build Coastguard Worker 
298*c8dee2aaSAndroid Build Coastguard Worker impl From<&ffi::Brush> for Brush {
from(src: &ffi::Brush) -> Self299*c8dee2aaSAndroid Build Coastguard Worker     fn from(src: &ffi::Brush) -> Self {
300*c8dee2aaSAndroid Build Coastguard Worker         match src.kind {
301*c8dee2aaSAndroid Build Coastguard Worker             ffi::BrushKind::Solid => Brush::Solid(Color::from(&src.data.solid)),
302*c8dee2aaSAndroid Build Coastguard Worker             _ => panic!("invalid brush kind"),
303*c8dee2aaSAndroid Build Coastguard Worker         }
304*c8dee2aaSAndroid Build Coastguard Worker     }
305*c8dee2aaSAndroid Build Coastguard Worker }
306*c8dee2aaSAndroid Build Coastguard Worker 
307*c8dee2aaSAndroid Build Coastguard Worker impl From<ffi::Fill> for Fill {
from(src: ffi::Fill) -> Self308*c8dee2aaSAndroid Build Coastguard Worker     fn from(src: ffi::Fill) -> Self {
309*c8dee2aaSAndroid Build Coastguard Worker         match src {
310*c8dee2aaSAndroid Build Coastguard Worker             ffi::Fill::NonZero => Self::NonZero,
311*c8dee2aaSAndroid Build Coastguard Worker             ffi::Fill::EvenOdd => Self::EvenOdd,
312*c8dee2aaSAndroid Build Coastguard Worker             _ => panic!("invalid fill type"),
313*c8dee2aaSAndroid Build Coastguard Worker         }
314*c8dee2aaSAndroid Build Coastguard Worker     }
315*c8dee2aaSAndroid Build Coastguard Worker }
316*c8dee2aaSAndroid Build Coastguard Worker 
317*c8dee2aaSAndroid Build Coastguard Worker impl From<&ffi::Stroke> for Stroke {
from(src: &ffi::Stroke) -> Self318*c8dee2aaSAndroid Build Coastguard Worker     fn from(src: &ffi::Stroke) -> Self {
319*c8dee2aaSAndroid Build Coastguard Worker         let cap = match src.cap {
320*c8dee2aaSAndroid Build Coastguard Worker             ffi::CapStyle::Butt => Cap::Butt,
321*c8dee2aaSAndroid Build Coastguard Worker             ffi::CapStyle::Square => Cap::Square,
322*c8dee2aaSAndroid Build Coastguard Worker             ffi::CapStyle::Round => Cap::Round,
323*c8dee2aaSAndroid Build Coastguard Worker             _ => panic!("invalid cap style"),
324*c8dee2aaSAndroid Build Coastguard Worker         };
325*c8dee2aaSAndroid Build Coastguard Worker         Self {
326*c8dee2aaSAndroid Build Coastguard Worker             width: src.width as f64,
327*c8dee2aaSAndroid Build Coastguard Worker             join: match src.join {
328*c8dee2aaSAndroid Build Coastguard Worker                 ffi::JoinStyle::Bevel => Join::Bevel,
329*c8dee2aaSAndroid Build Coastguard Worker                 ffi::JoinStyle::Miter => Join::Miter,
330*c8dee2aaSAndroid Build Coastguard Worker                 ffi::JoinStyle::Round => Join::Round,
331*c8dee2aaSAndroid Build Coastguard Worker                 _ => panic!("invalid join style"),
332*c8dee2aaSAndroid Build Coastguard Worker             },
333*c8dee2aaSAndroid Build Coastguard Worker             miter_limit: src.miter_limit as f64,
334*c8dee2aaSAndroid Build Coastguard Worker             start_cap: cap,
335*c8dee2aaSAndroid Build Coastguard Worker             end_cap: cap,
336*c8dee2aaSAndroid Build Coastguard Worker             // Skia expands a dash effect by transforming the encoded path, so don't need to handle
337*c8dee2aaSAndroid Build Coastguard Worker             // that here.
338*c8dee2aaSAndroid Build Coastguard Worker             dash_pattern: Default::default(),
339*c8dee2aaSAndroid Build Coastguard Worker             dash_offset: 0.,
340*c8dee2aaSAndroid Build Coastguard Worker         }
341*c8dee2aaSAndroid Build Coastguard Worker     }
342*c8dee2aaSAndroid Build Coastguard Worker }
343*c8dee2aaSAndroid Build Coastguard Worker 
344*c8dee2aaSAndroid Build Coastguard Worker impl From<&vello_encoding::WorkgroupSize> for ffi::WorkgroupSize {
from(src: &vello_encoding::WorkgroupSize) -> Self345*c8dee2aaSAndroid Build Coastguard Worker     fn from(src: &vello_encoding::WorkgroupSize) -> Self {
346*c8dee2aaSAndroid Build Coastguard Worker         Self {
347*c8dee2aaSAndroid Build Coastguard Worker             x: src.0,
348*c8dee2aaSAndroid Build Coastguard Worker             y: src.1,
349*c8dee2aaSAndroid Build Coastguard Worker             z: src.2,
350*c8dee2aaSAndroid Build Coastguard Worker         }
351*c8dee2aaSAndroid Build Coastguard Worker     }
352*c8dee2aaSAndroid Build Coastguard Worker }
353*c8dee2aaSAndroid Build Coastguard Worker 
354*c8dee2aaSAndroid Build Coastguard Worker impl From<&vello_encoding::WorkgroupCounts> for ffi::DispatchInfo {
from(src: &vello_encoding::WorkgroupCounts) -> Self355*c8dee2aaSAndroid Build Coastguard Worker     fn from(src: &vello_encoding::WorkgroupCounts) -> Self {
356*c8dee2aaSAndroid Build Coastguard Worker         Self {
357*c8dee2aaSAndroid Build Coastguard Worker             use_large_path_scan: src.use_large_path_scan,
358*c8dee2aaSAndroid Build Coastguard Worker             path_reduce: (&src.path_reduce).into(),
359*c8dee2aaSAndroid Build Coastguard Worker             path_reduce2: (&src.path_reduce2).into(),
360*c8dee2aaSAndroid Build Coastguard Worker             path_scan1: (&src.path_scan1).into(),
361*c8dee2aaSAndroid Build Coastguard Worker             path_scan: (&src.path_scan).into(),
362*c8dee2aaSAndroid Build Coastguard Worker             bbox_clear: (&src.bbox_clear).into(),
363*c8dee2aaSAndroid Build Coastguard Worker             flatten: (&src.flatten).into(),
364*c8dee2aaSAndroid Build Coastguard Worker             draw_reduce: (&src.draw_reduce).into(),
365*c8dee2aaSAndroid Build Coastguard Worker             draw_leaf: (&src.draw_leaf).into(),
366*c8dee2aaSAndroid Build Coastguard Worker             clip_reduce: (&src.clip_reduce).into(),
367*c8dee2aaSAndroid Build Coastguard Worker             clip_leaf: (&src.clip_leaf).into(),
368*c8dee2aaSAndroid Build Coastguard Worker             binning: (&src.binning).into(),
369*c8dee2aaSAndroid Build Coastguard Worker             tile_alloc: (&src.tile_alloc).into(),
370*c8dee2aaSAndroid Build Coastguard Worker             path_count_setup: (&src.path_count_setup).into(),
371*c8dee2aaSAndroid Build Coastguard Worker             backdrop: (&src.backdrop).into(),
372*c8dee2aaSAndroid Build Coastguard Worker             coarse: (&src.coarse).into(),
373*c8dee2aaSAndroid Build Coastguard Worker             path_tiling_setup: (&src.path_tiling_setup).into(),
374*c8dee2aaSAndroid Build Coastguard Worker             fine: (&src.fine).into(),
375*c8dee2aaSAndroid Build Coastguard Worker         }
376*c8dee2aaSAndroid Build Coastguard Worker     }
377*c8dee2aaSAndroid Build Coastguard Worker }
378*c8dee2aaSAndroid Build Coastguard Worker 
379*c8dee2aaSAndroid Build Coastguard Worker impl From<&vello_encoding::BufferSizes> for ffi::BufferSizes {
from(src: &vello_encoding::BufferSizes) -> Self380*c8dee2aaSAndroid Build Coastguard Worker     fn from(src: &vello_encoding::BufferSizes) -> Self {
381*c8dee2aaSAndroid Build Coastguard Worker         Self {
382*c8dee2aaSAndroid Build Coastguard Worker             path_reduced: src.path_reduced.size_in_bytes(),
383*c8dee2aaSAndroid Build Coastguard Worker             path_reduced2: src.path_reduced2.size_in_bytes(),
384*c8dee2aaSAndroid Build Coastguard Worker             path_reduced_scan: src.path_reduced_scan.size_in_bytes(),
385*c8dee2aaSAndroid Build Coastguard Worker             path_monoids: src.path_monoids.size_in_bytes(),
386*c8dee2aaSAndroid Build Coastguard Worker             path_bboxes: src.path_bboxes.size_in_bytes(),
387*c8dee2aaSAndroid Build Coastguard Worker             draw_reduced: src.draw_reduced.size_in_bytes(),
388*c8dee2aaSAndroid Build Coastguard Worker             draw_monoids: src.draw_monoids.size_in_bytes(),
389*c8dee2aaSAndroid Build Coastguard Worker             info: src.info.size_in_bytes(),
390*c8dee2aaSAndroid Build Coastguard Worker             clip_inps: src.clip_inps.size_in_bytes(),
391*c8dee2aaSAndroid Build Coastguard Worker             clip_els: src.clip_els.size_in_bytes(),
392*c8dee2aaSAndroid Build Coastguard Worker             clip_bics: src.clip_bics.size_in_bytes(),
393*c8dee2aaSAndroid Build Coastguard Worker             clip_bboxes: src.clip_bboxes.size_in_bytes(),
394*c8dee2aaSAndroid Build Coastguard Worker             draw_bboxes: src.draw_bboxes.size_in_bytes(),
395*c8dee2aaSAndroid Build Coastguard Worker             bump_alloc: src.bump_alloc.size_in_bytes(),
396*c8dee2aaSAndroid Build Coastguard Worker             indirect_count: src.indirect_count.size_in_bytes(),
397*c8dee2aaSAndroid Build Coastguard Worker             bin_headers: src.bin_headers.size_in_bytes(),
398*c8dee2aaSAndroid Build Coastguard Worker             paths: src.paths.size_in_bytes(),
399*c8dee2aaSAndroid Build Coastguard Worker             lines: src.lines.size_in_bytes(),
400*c8dee2aaSAndroid Build Coastguard Worker             bin_data: src.bin_data.size_in_bytes(),
401*c8dee2aaSAndroid Build Coastguard Worker             tiles: src.tiles.size_in_bytes(),
402*c8dee2aaSAndroid Build Coastguard Worker             seg_counts: src.seg_counts.size_in_bytes(),
403*c8dee2aaSAndroid Build Coastguard Worker             segments: src.segments.size_in_bytes(),
404*c8dee2aaSAndroid Build Coastguard Worker             ptcl: src.ptcl.size_in_bytes(),
405*c8dee2aaSAndroid Build Coastguard Worker         }
406*c8dee2aaSAndroid Build Coastguard Worker     }
407*c8dee2aaSAndroid Build Coastguard Worker }
408