33
44//! Abstraction for generating strips from paths.
55
6+ use crate :: clip:: { PathDataRef , intersect} ;
67use crate :: fearless_simd:: Level ;
78use crate :: flatten:: { FlattenCtx , Line } ;
89use crate :: kurbo:: { Affine , PathEl , Stroke } ;
@@ -14,7 +15,7 @@ use alloc::vec::Vec;
1415use peniko:: kurbo:: StrokeCtx ;
1516
1617/// A storage for storing strip-related data.
17- #[ derive( Debug , Default ) ]
18+ #[ derive( Debug , Default , PartialEq , Eq ) ]
1819pub struct StripStorage {
1920 /// The strips in the storage.
2021 pub strips : Vec < Strip > ,
@@ -49,15 +50,22 @@ impl StripStorage {
4950 pub fn is_empty ( & self ) -> bool {
5051 self . strips . is_empty ( ) && self . alphas . is_empty ( )
5152 }
53+
54+ /// Extend the current strip storage with the data from another storage.
55+ pub fn extend ( & mut self , other : & Self ) {
56+ self . strips . extend ( & other. strips ) ;
57+ self . alphas . extend ( & other. alphas ) ;
58+ }
5259}
5360
5461/// An object for easily generating strips for a filled/stroked path.
5562#[ derive( Debug ) ]
5663pub struct StripGenerator {
57- level : Level ,
64+ pub ( crate ) level : Level ,
5865 line_buf : Vec < Line > ,
5966 flatten_ctx : FlattenCtx ,
6067 stroke_ctx : StrokeCtx ,
68+ temp_storage : StripStorage ,
6169 tiles : Tiles ,
6270 width : u16 ,
6371 height : u16 ,
@@ -72,6 +80,7 @@ impl StripGenerator {
7280 tiles : Tiles :: new ( level) ,
7381 flatten_ctx : FlattenCtx :: default ( ) ,
7482 stroke_ctx : StrokeCtx :: default ( ) ,
83+ temp_storage : StripStorage :: default ( ) ,
7584 width,
7685 height,
7786 }
@@ -85,6 +94,7 @@ impl StripGenerator {
8594 transform : Affine ,
8695 aliasing_threshold : Option < u8 > ,
8796 strip_storage : & mut StripStorage ,
97+ clip_path : Option < PathDataRef < ' _ > > ,
8898 ) {
8999 flatten:: fill (
90100 self . level ,
@@ -93,7 +103,8 @@ impl StripGenerator {
93103 & mut self . line_buf ,
94104 & mut self . flatten_ctx ,
95105 ) ;
96- self . make_strips ( strip_storage, fill_rule, aliasing_threshold) ;
106+
107+ self . generate_with_clip ( aliasing_threshold, strip_storage, fill_rule, clip_path) ;
97108 }
98109
99110 /// Generate the strips for a stroked path.
@@ -104,6 +115,7 @@ impl StripGenerator {
104115 transform : Affine ,
105116 aliasing_threshold : Option < u8 > ,
106117 strip_storage : & mut StripStorage ,
118+ clip_path : Option < PathDataRef < ' _ > > ,
107119 ) {
108120 flatten:: stroke (
109121 self . level ,
@@ -114,34 +126,64 @@ impl StripGenerator {
114126 & mut self . flatten_ctx ,
115127 & mut self . stroke_ctx ,
116128 ) ;
117- self . make_strips ( strip_storage, Fill :: NonZero , aliasing_threshold) ;
129+ self . generate_with_clip ( aliasing_threshold, strip_storage, Fill :: NonZero , clip_path) ;
130+ }
131+
132+ fn generate_with_clip (
133+ & mut self ,
134+ aliasing_threshold : Option < u8 > ,
135+ strip_storage : & mut StripStorage ,
136+ fill_rule : Fill ,
137+ clip_path : Option < PathDataRef < ' _ > > ,
138+ ) {
139+ if strip_storage. generation_mode == GenerationMode :: Replace {
140+ strip_storage. strips . clear ( ) ;
141+ }
142+
143+ if let Some ( clip_path) = clip_path {
144+ self . make_strips ( strip_storage, fill_rule, aliasing_threshold, true ) ;
145+ let path_data = PathDataRef {
146+ strips : & self . temp_storage . strips ,
147+ alphas : & self . temp_storage . alphas ,
148+ } ;
149+
150+ intersect ( self . level , clip_path, path_data, strip_storage) ;
151+ } else {
152+ self . make_strips ( strip_storage, fill_rule, aliasing_threshold, false ) ;
153+ }
118154 }
119155
120156 /// Reset the strip generator.
121157 pub fn reset ( & mut self ) {
122158 self . line_buf . clear ( ) ;
123159 self . tiles . reset ( ) ;
160+ self . temp_storage . clear ( ) ;
124161 }
125162
126163 fn make_strips (
127164 & mut self ,
128165 strip_storage : & mut StripStorage ,
129166 fill_rule : Fill ,
130167 aliasing_threshold : Option < u8 > ,
168+ temp : bool ,
131169 ) {
132170 self . tiles
133171 . make_tiles ( & self . line_buf , self . width , self . height ) ;
134172 self . tiles . sort_tiles ( ) ;
135173
136- if strip_storage. generation_mode == GenerationMode :: Replace {
137- strip_storage. strips . clear ( ) ;
138- }
174+ let storage = if temp {
175+ self . temp_storage . clear ( ) ;
176+
177+ & mut self . temp_storage
178+ } else {
179+ strip_storage
180+ } ;
139181
140182 strip:: render (
141183 self . level ,
142184 & self . tiles ,
143- & mut strip_storage . strips ,
144- & mut strip_storage . alphas ,
185+ & mut storage . strips ,
186+ & mut storage . alphas ,
145187 fill_rule,
146188 aliasing_threshold,
147189 & self . line_buf ,
@@ -168,6 +210,7 @@ mod tests {
168210 Affine :: IDENTITY ,
169211 None ,
170212 & mut storage,
213+ None ,
171214 ) ;
172215
173216 assert ! ( !generator. line_buf. is_empty( ) ) ;
0 commit comments