33
44using System ;
55using System . Buffers ;
6-
6+ using System . Runtime . CompilerServices ;
77using SixLabors . ImageSharp . Advanced ;
8- using SixLabors . ImageSharp . Advanced . ParallelUtils ;
8+ using SixLabors . ImageSharp . Memory ;
99using SixLabors . ImageSharp . PixelFormats ;
1010
1111namespace SixLabors . ImageSharp . Processing . Processors . Drawing
@@ -28,25 +28,10 @@ public FillProcessor(Configuration configuration, FillProcessor definition, Imag
2828 /// <inheritdoc/>
2929 protected override void OnFrameApply ( ImageFrame < TPixel > source )
3030 {
31- Rectangle sourceRectangle = this . SourceRectangle ;
3231 Configuration configuration = this . Configuration ;
33- int startX = sourceRectangle . X ;
34- int endX = sourceRectangle . Right ;
35- int startY = sourceRectangle . Y ;
36- int endY = sourceRectangle . Bottom ;
37-
38- // Align start/end positions.
39- int minX = Math . Max ( 0 , startX ) ;
40- int maxX = Math . Min ( source . Width , endX ) ;
41- int minY = Math . Max ( 0 , startY ) ;
42- int maxY = Math . Min ( source . Height , endY ) ;
43-
44- int width = maxX - minX ;
45-
46- var workingRect = Rectangle . FromLTRB ( minX , minY , maxX , maxY ) ;
47-
4832 IBrush brush = this . definition . Brush ;
4933 GraphicsOptions options = this . definition . Options ;
34+ var interest = Rectangle . Intersect ( this . SourceRectangle , source . Bounds ( ) ) ;
5035
5136 // If there's no reason for blending, then avoid it.
5237 if ( this . IsSolidBrushWithoutBlending ( out SolidBrush solidBrush ) )
@@ -56,54 +41,29 @@ protected override void OnFrameApply(ImageFrame<TPixel> source)
5641
5742 TPixel colorPixel = solidBrush . Color . ToPixel < TPixel > ( ) ;
5843
59- ParallelHelper . IterateRows (
60- workingRect ,
44+ var solidOperation = new SolidBrushRowIntervalOperation ( interest , source , colorPixel ) ;
45+ ParallelRowIterator . IterateRows (
46+ interest ,
6147 parallelSettings ,
62- rows =>
63- {
64- for ( int y = rows . Min ; y < rows . Max ; y ++ )
65- {
66- source . GetPixelRowSpan ( y ) . Slice ( minX , width ) . Fill ( colorPixel ) ;
67- }
68- } ) ;
48+ in solidOperation ) ;
49+
50+ return ;
6951 }
70- else
71- {
72- // Reset offset if necessary.
73- if ( minX > 0 )
74- {
75- startX = 0 ;
76- }
7752
78- if ( minY > 0 )
79- {
80- startY = 0 ;
81- }
53+ using IMemoryOwner < float > amount = configuration . MemoryAllocator . Allocate < float > ( interest . Width ) ;
54+ using BrushApplicator < TPixel > applicator = brush . CreateApplicator (
55+ configuration ,
56+ options ,
57+ source ,
58+ interest ) ;
8259
83- using ( IMemoryOwner < float > amount = source . MemoryAllocator . Allocate < float > ( width ) )
84- using ( BrushApplicator < TPixel > applicator = brush . CreateApplicator (
85- configuration ,
86- options ,
87- source ,
88- sourceRectangle ) )
89- {
90- amount . Memory . Span . Fill ( 1F ) ;
91-
92- ParallelHelper . IterateRows (
93- workingRect ,
94- configuration ,
95- rows =>
96- {
97- for ( int y = rows . Min ; y < rows . Max ; y ++ )
98- {
99- int offsetY = y - startY ;
100- int offsetX = minX - startX ;
101-
102- applicator . Apply ( amount . Memory . Span , offsetX , offsetY ) ;
103- }
104- } ) ;
105- }
106- }
60+ amount . Memory . Span . Fill ( 1F ) ;
61+
62+ var operation = new RowIntervalOperation ( interest , applicator , amount . Memory ) ;
63+ ParallelRowIterator . IterateRows (
64+ configuration ,
65+ interest ,
66+ in operation ) ;
10767 }
10868
10969 private bool IsSolidBrushWithoutBlending ( out SolidBrush solidBrush )
@@ -117,5 +77,57 @@ private bool IsSolidBrushWithoutBlending(out SolidBrush solidBrush)
11777
11878 return this . definition . Options . IsOpaqueColorWithoutBlending ( solidBrush . Color ) ;
11979 }
80+
81+ private readonly struct SolidBrushRowIntervalOperation : IRowIntervalOperation
82+ {
83+ private readonly Rectangle bounds ;
84+ private readonly ImageFrame < TPixel > source ;
85+ private readonly TPixel color ;
86+
87+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
88+ public SolidBrushRowIntervalOperation ( Rectangle bounds , ImageFrame < TPixel > source , TPixel color )
89+ {
90+ this . bounds = bounds ;
91+ this . source = source ;
92+ this . color = color ;
93+ }
94+
95+ /// <inheritdoc/>
96+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
97+ public void Invoke ( in RowInterval rows )
98+ {
99+ for ( int y = rows . Min ; y < rows . Max ; y ++ )
100+ {
101+ this . source . GetPixelRowSpan ( y ) . Slice ( this . bounds . X , this . bounds . Width ) . Fill ( this . color ) ;
102+ }
103+ }
104+ }
105+
106+ private readonly struct RowIntervalOperation : IRowIntervalOperation
107+ {
108+ private readonly Memory < float > amount ;
109+ private readonly Rectangle bounds ;
110+ private readonly BrushApplicator < TPixel > applicator ;
111+
112+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
113+ public RowIntervalOperation ( Rectangle bounds , BrushApplicator < TPixel > applicator , Memory < float > amount )
114+ {
115+ this . bounds = bounds ;
116+ this . applicator = applicator ;
117+ this . amount = amount ;
118+ }
119+
120+ /// <inheritdoc/>
121+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
122+ public void Invoke ( in RowInterval rows )
123+ {
124+ Span < float > amountSpan = this . amount . Span ;
125+ int x = this . bounds . X ;
126+ for ( int y = rows . Min ; y < rows . Max ; y ++ )
127+ {
128+ this . applicator . Apply ( amountSpan , x , y ) ;
129+ }
130+ }
131+ }
120132 }
121133}
0 commit comments