@@ -194,7 +194,6 @@ async fn brush(_: impl Ctx, mut image_frame_table: Table<Raster<CPU>>, strokes:
194194 let background_bounds = bbox. to_transform ( ) ;
195195
196196 let mut draw_strokes: Vec < _ > = strokes. iter ( ) . filter ( |& s| !matches ! ( s. style. blend_mode, BlendMode :: Erase | BlendMode :: Restore ) ) . cloned ( ) . collect ( ) ;
197- let erase_restore_strokes: Vec < _ > = strokes. iter ( ) . filter ( |& s| matches ! ( s. style. blend_mode, BlendMode :: Erase | BlendMode :: Restore ) ) . cloned ( ) . collect ( ) ;
198197
199198 let mut brush_plan = cache. compute_brush_plan ( table_row, & draw_strokes) ;
200199
@@ -258,16 +257,16 @@ async fn brush(_: impl Ctx, mut image_frame_table: Table<Raster<CPU>>, strokes:
258257 actual_image = blend_with_mode ( actual_image, stroke_texture, stroke. style . blend_mode , ( stroke. style . color . a ( ) * 100. ) as f64 ) ;
259258 }
260259
261- let has_erase_strokes = strokes. iter ( ) . any ( |s| s. style . blend_mode == BlendMode :: Erase ) ;
262- if has_erase_strokes {
260+ let has_erase_or_restore_strokes = strokes. iter ( ) . any ( |s| matches ! ( s. style. blend_mode, BlendMode :: Erase | BlendMode :: Restore ) ) ;
261+ if has_erase_or_restore_strokes {
263262 let opaque_image = Image :: new ( bbox. size ( ) . x as u32 , bbox. size ( ) . y as u32 , Color :: WHITE ) ;
264263 let mut erase_restore_mask = TableRow {
265264 element : Raster :: new_cpu ( opaque_image) ,
266265 transform : background_bounds,
267266 ..Default :: default ( )
268267 } ;
269268
270- for stroke in erase_restore_strokes {
269+ for stroke in strokes {
271270 let mut brush_texture = cache. get_cached_brush ( & stroke. style ) ;
272271 if brush_texture. is_none ( ) {
273272 let tex = create_brush_texture ( & stroke. style ) . await ;
@@ -277,28 +276,20 @@ async fn brush(_: impl Ctx, mut image_frame_table: Table<Raster<CPU>>, strokes:
277276 let brush_texture = brush_texture. unwrap ( ) ;
278277 let positions: Vec < _ > = stroke. compute_blit_points ( ) . into_iter ( ) . collect ( ) ;
279278
280- match stroke. style . blend_mode {
281- BlendMode :: Erase => {
282- let blend_params = FnNode :: new ( |( a, b) | blend_colors ( a, b, BlendMode :: Erase , 1. ) ) ;
283- let blit_node = BlitNode :: new (
284- FutureWrapperNode :: new ( ClonedNode :: new ( brush_texture) ) ,
285- FutureWrapperNode :: new ( ClonedNode :: new ( positions) ) ,
286- FutureWrapperNode :: new ( ClonedNode :: new ( blend_params) ) ,
287- ) ;
288- erase_restore_mask = blit_node. eval ( Table :: new_from_row ( erase_restore_mask) ) . await . into_iter ( ) . next ( ) . unwrap_or_default ( ) ;
289- }
290- // Yes, this is essentially the same as the above, but we duplicate to inline the blend mode.
291- BlendMode :: Restore => {
292- let blend_params = FnNode :: new ( |( a, b) | blend_colors ( a, b, BlendMode :: Restore , 1. ) ) ;
293- let blit_node = BlitNode :: new (
294- FutureWrapperNode :: new ( ClonedNode :: new ( brush_texture) ) ,
295- FutureWrapperNode :: new ( ClonedNode :: new ( positions) ) ,
296- FutureWrapperNode :: new ( ClonedNode :: new ( blend_params) ) ,
297- ) ;
298- erase_restore_mask = blit_node. eval ( Table :: new_from_row ( erase_restore_mask) ) . await . into_iter ( ) . next ( ) . unwrap_or_default ( ) ;
299- }
300- _ => unreachable ! ( ) ,
301- }
279+ // For mask composition: Erase subtracts alpha, Restore adds alpha, and Draw acts like Restore to allow repainting erased areas.
280+ let mask_blend_mode = match stroke. style . blend_mode {
281+ BlendMode :: Erase => BlendMode :: Erase ,
282+ BlendMode :: Restore => BlendMode :: Restore ,
283+ _ => BlendMode :: Restore ,
284+ } ;
285+
286+ let blend_params = FnNode :: new ( move |( a, b) | blend_colors ( a, b, mask_blend_mode, 1. ) ) ;
287+ let blit_node = BlitNode :: new (
288+ FutureWrapperNode :: new ( ClonedNode :: new ( brush_texture) ) ,
289+ FutureWrapperNode :: new ( ClonedNode :: new ( positions) ) ,
290+ FutureWrapperNode :: new ( ClonedNode :: new ( blend_params) ) ,
291+ ) ;
292+ erase_restore_mask = blit_node. eval ( Table :: new_from_row ( erase_restore_mask) ) . await . into_iter ( ) . next ( ) . unwrap_or_default ( ) ;
302293 }
303294
304295 let blend_params = FnNode :: new ( |( a, b) | blend_colors ( a, b, BlendMode :: MultiplyAlpha , 1. ) ) ;
0 commit comments