vello_common/
strip_generator.rs1use crate::fearless_simd::Level;
7use crate::flatten::{FlattenCtx, Line};
8use crate::kurbo::{Affine, PathEl, Stroke};
9use crate::peniko::Fill;
10use crate::strip::Strip;
11use crate::tile::Tiles;
12use crate::{flatten, strip};
13use alloc::vec::Vec;
14
15#[derive(Debug)]
17pub struct StripGenerator {
18 level: Level,
19 alphas: Vec<u8>,
20 line_buf: Vec<Line>,
21 flatten_ctx: FlattenCtx,
22 tiles: Tiles,
23 strip_buf: Vec<Strip>,
24 width: u16,
25 height: u16,
26}
27
28impl StripGenerator {
29 pub fn new(width: u16, height: u16, level: Level) -> Self {
31 Self {
32 alphas: Vec::new(),
33 level,
34 line_buf: Vec::new(),
35 tiles: Tiles::new(level),
36 strip_buf: Vec::new(),
37 flatten_ctx: FlattenCtx::default(),
38 width,
39 height,
40 }
41 }
42
43 pub fn generate_filled_path<'a>(
45 &'a mut self,
46 path: impl IntoIterator<Item = PathEl>,
47 fill_rule: Fill,
48 transform: Affine,
49 anti_alias: bool,
50 func: impl FnOnce(&'a [Strip]),
51 ) {
52 flatten::fill(
53 self.level,
54 path,
55 transform,
56 &mut self.line_buf,
57 &mut self.flatten_ctx,
58 );
59 self.make_strips(fill_rule, anti_alias);
60 func(&mut self.strip_buf);
61 }
62
63 pub fn generate_stroked_path<'a>(
65 &'a mut self,
66 path: impl IntoIterator<Item = PathEl>,
67 stroke: &Stroke,
68 transform: Affine,
69 anti_alias: bool,
70 func: impl FnOnce(&'a [Strip]),
71 ) {
72 flatten::stroke(
73 self.level,
74 path,
75 stroke,
76 transform,
77 &mut self.line_buf,
78 &mut self.flatten_ctx,
79 );
80 self.make_strips(Fill::NonZero, anti_alias);
81 func(&mut self.strip_buf);
82 }
83
84 pub fn alpha_buf(&self) -> &[u8] {
86 &self.alphas
87 }
88
89 pub fn extend_alpha_buf(&mut self, alphas: &[u8]) {
91 self.alphas.extend_from_slice(alphas);
92 }
93
94 pub fn set_alpha_buf(&mut self, alpha_buf: Vec<u8>) {
96 self.alphas = alpha_buf;
97 }
98
99 pub fn take_alpha_buf(&mut self) -> Vec<u8> {
101 core::mem::take(&mut self.alphas)
102 }
103
104 pub fn replace_alpha_buf(&mut self, alphas: Vec<u8>) -> Vec<u8> {
106 core::mem::replace(&mut self.alphas, alphas)
107 }
108
109 pub fn reset(&mut self) {
111 self.line_buf.clear();
112 self.tiles.reset();
113 self.alphas.clear();
114 self.strip_buf.clear();
115 }
116
117 fn make_strips(&mut self, fill_rule: Fill, anti_alias: bool) {
118 self.tiles
119 .make_tiles(&self.line_buf, self.width, self.height);
120 self.tiles.sort_tiles();
121 strip::render(
122 self.level,
123 &self.tiles,
124 &mut self.strip_buf,
125 &mut self.alphas,
126 fill_rule,
127 anti_alias,
128 &self.line_buf,
129 );
130 }
131}
132
133#[cfg(test)]
134mod tests {
135 use crate::fearless_simd::Level;
136 use crate::kurbo::{Affine, Rect, Shape};
137 use crate::peniko::Fill;
138 use crate::strip_generator::StripGenerator;
139
140 #[test]
141 fn reset_strip_generator() {
142 let mut generator = StripGenerator::new(100, 100, Level::fallback());
143 let rect = Rect::new(0.0, 0.0, 100.0, 100.0);
144
145 generator.generate_filled_path(
146 rect.to_path(0.1),
147 Fill::NonZero,
148 Affine::IDENTITY,
149 true,
150 |_| {},
151 );
152
153 assert!(!generator.line_buf.is_empty());
154 assert!(!generator.strip_buf.is_empty());
155 assert!(!generator.alphas.is_empty());
156
157 generator.reset();
158
159 assert!(generator.line_buf.is_empty());
160 assert!(generator.strip_buf.is_empty());
161 assert!(generator.alphas.is_empty());
162 }
163}