@@ -56,8 +56,11 @@ public void Flush_SamePathDifferentBrushes_ReusesSourcePath()
5656 canvas . Flush ( ) ;
5757
5858 Assert . Equal ( 2 , backend . PreparedCommands . Count ) ;
59- Assert . NotNull ( backend . PreparedCommands [ 0 ] . SourcePath ) ;
60- Assert . Same ( backend . PreparedCommands [ 0 ] . SourcePath , backend . PreparedCommands [ 1 ] . SourcePath ) ;
59+
60+ PathCompositionSceneCommand firstCommand = Assert . IsType < PathCompositionSceneCommand > ( backend . PreparedCommands [ 0 ] ) ;
61+ PathCompositionSceneCommand secondCommand = Assert . IsType < PathCompositionSceneCommand > ( backend . PreparedCommands [ 1 ] ) ;
62+ Assert . NotNull ( firstCommand . Command . SourcePath ) ;
63+ Assert . Same ( firstCommand . Command . SourcePath , secondCommand . Command . SourcePath ) ;
6164 }
6265
6366 [ Fact ]
@@ -112,33 +115,35 @@ public void Flush_RepeatedGlyphs_ReusesCoverageDefinitions()
112115 canvas . DrawText ( textOptions , text , brush , pen : null ) ;
113116 canvas . Flush ( ) ;
114117
115- int totalCommands = backend . Definitions . Sum ( b => b . Commands . Count ) ;
118+ int totalCommands = backend . PreparedCommands . Count ;
116119 Assert . True ( totalCommands > 0 ) ;
117120 Assert . True (
118121 backend . Definitions . Count < 200 ,
119122 $ "Expected coverage reuse but got { backend . Definitions . Count } coverage definitions for 200 glyphs.") ;
120123 }
121124
122125 [ Fact ]
123- public void Flush_SupportedSolidStroke_PreparesCenterlinePath ( )
126+ public void Flush_SupportedSolidStroke_PreparesLineSegmentSceneCommand ( )
124127 {
125128 Configuration configuration = new ( ) ;
126129 CapturingBackend backend = new ( ) ;
127130 configuration . SetDrawingBackend ( backend ) ;
128- using Image < Rgba32 > image = new ( 80 , 80 ) ;
129- Buffer2DRegion < Rgba32 > region = new ( image . Frames . RootFrame . PixelBuffer , image . Bounds ) ;
131+ using Image < Rgba32 > image = new ( configuration , 80 , 80 ) ;
130132
131- using DrawingCanvas < Rgba32 > canvas = new ( configuration , region , new DrawingOptions ( ) ) ;
133+ using DrawingCanvas < Rgba32 > canvas = DrawingCanvas < Rgba32 > . FromRootFrame ( image , new DrawingOptions ( ) ) ;
132134 canvas . DrawLine ( new SolidPen ( Color . Red , 5F ) , new PointF ( 8 , 12 ) , new PointF ( 70 , 64 ) ) ;
133135 canvas . Flush ( ) ;
134136
135137 Assert . Single ( backend . PreparedCommands ) ;
136- Assert . NotNull ( backend . PreparedCommands [ 0 ] . SourcePath ) ;
137- Assert . NotNull ( backend . PreparedCommands [ 0 ] . Pen ) ;
138+
139+ LineSegmentCompositionSceneCommand command = Assert . IsType < LineSegmentCompositionSceneCommand > ( backend . PreparedCommands [ 0 ] ) ;
140+ Assert . Equal ( new PointF ( 8 , 12 ) , command . Command . SourceStart ) ;
141+ Assert . Equal ( new PointF ( 70 , 64 ) , command . Command . SourceEnd ) ;
142+ Assert . NotNull ( command . Command . Pen ) ;
138143 }
139144
140145 [ Fact ]
141- public void Flush_DashedStroke_PreparesCenterlinePath ( )
146+ public void Flush_DashedStroke_PreparesPathSceneCommand ( )
142147 {
143148 Configuration configuration = new ( ) ;
144149 CapturingBackend backend = new ( ) ;
@@ -151,12 +156,14 @@ public void Flush_DashedStroke_PreparesCenterlinePath()
151156 canvas . Flush ( ) ;
152157
153158 Assert . Single ( backend . PreparedCommands ) ;
154- Assert . NotNull ( backend . PreparedCommands [ 0 ] . SourcePath ) ;
155- Assert . NotNull ( backend . PreparedCommands [ 0 ] . Pen ) ;
159+
160+ PathCompositionSceneCommand command = Assert . IsType < PathCompositionSceneCommand > ( backend . PreparedCommands [ 0 ] ) ;
161+ Assert . NotNull ( command . Command . SourcePath ) ;
162+ Assert . NotNull ( command . Command . Pen ) ;
156163 }
157164
158165 [ Fact ]
159- public void Flush_MiterStroke_PreparesCenterlinePath ( )
166+ public void Flush_MiterStroke_PreparesPathSceneCommand ( )
160167 {
161168 Configuration configuration = new ( ) ;
162169 CapturingBackend backend = new ( ) ;
@@ -173,19 +180,21 @@ public void Flush_MiterStroke_PreparesCenterlinePath()
173180 } ;
174181
175182 using DrawingCanvas < Rgba32 > canvas = new ( configuration , region , new DrawingOptions ( ) ) ;
176- canvas . Draw ( new SolidPen ( options ) , new Path ( new [ ] { new PointF ( 8 , 40 ) , new PointF ( 40 , 8 ) , new PointF ( 72 , 40 ) } ) ) ;
183+ canvas . Draw ( new SolidPen ( options ) , new Path ( [ new PointF ( 8 , 40 ) , new PointF ( 40 , 8 ) , new PointF ( 72 , 40 ) ] ) ) ;
177184 canvas . Flush ( ) ;
178185
179186 Assert . Single ( backend . PreparedCommands ) ;
180- Assert . NotNull ( backend . PreparedCommands [ 0 ] . SourcePath ) ;
181- Assert . NotNull ( backend . PreparedCommands [ 0 ] . Pen ) ;
187+
188+ PathCompositionSceneCommand command = Assert . IsType < PathCompositionSceneCommand > ( backend . PreparedCommands [ 0 ] ) ;
189+ Assert . NotNull ( command . Command . SourcePath ) ;
190+ Assert . NotNull ( command . Command . Pen ) ;
182191 }
183192
184193 private sealed class CapturingBackend : IDrawingBackend
185194 {
186195 public List < CapturedCoverageDefinition > Definitions { get ; } = [ ] ;
187196
188- public IReadOnlyList < CompositionCommand > PreparedCommands { get ; private set ; } = Array . Empty < CompositionCommand > ( ) ;
197+ public IReadOnlyList < CompositionSceneCommand > PreparedCommands { get ; private set ; } = Array . Empty < CompositionSceneCommand > ( ) ;
189198
190199 public bool HasDefinition { get ; private set ; }
191200
@@ -206,33 +215,19 @@ public void FlushCompositions<TPixel>(
206215 CompositionScene compositionScene )
207216 where TPixel : unmanaged, IPixel < TPixel >
208217 {
209- List < CompositionCommand > preparedCommands = [ ] ;
210- for ( int i = 0 ; i < compositionScene . Commands . Count ; i ++ )
211- {
212- if ( compositionScene . Commands [ i ] is PathCompositionSceneCommand pathCommand )
213- {
214- preparedCommands . Add ( pathCommand . Command ) ;
215- }
216- }
217-
218- this . PreparedCommands = preparedCommands ;
218+ this . PreparedCommands = compositionScene . Commands . ToArray ( ) ;
219219
220220 Dictionary < CoverageDefinitionKey , int > definitionIndices = [ ] ;
221- for ( int i = 0 ; i < compositionScene . Commands . Count ; i ++ )
221+ for ( int i = 0 ; i < this . PreparedCommands . Count ; i ++ )
222222 {
223- if ( compositionScene . Commands [ i ] is not PathCompositionSceneCommand pathCommand )
223+ if ( this . PreparedCommands [ i ] is not PathCompositionSceneCommand pathCommand )
224224 {
225225 continue ;
226226 }
227227
228228 CompositionCommand command = pathCommand . Command ;
229- // if (!command.IsVisible)
230- // {
231- // continue;
232- // }
233-
234- IPath ? SourcePath = command . SourcePath ;
235- if ( SourcePath is null )
229+ IPath sourcePath = command . SourcePath ;
230+ if ( sourcePath is null )
236231 {
237232 continue ;
238233 }
@@ -246,7 +241,7 @@ public void FlushCompositions<TPixel>(
246241 definitionIndices . Add ( key , definitionIndex ) ;
247242 this . Definitions . Add (
248243 new CapturedCoverageDefinition (
249- SourcePath ,
244+ sourcePath ,
250245 rasterizerOptions ,
251246 command . DestinationOffset ,
252247 [ command ] ) ) ;
@@ -274,20 +269,32 @@ public bool TryReadRegion<TPixel>(
274269 where TPixel : unmanaged, IPixel < TPixel >
275270 => false ;
276271
277- public sealed class CapturedCoverageDefinition ( IPath SourcePath , RasterizerOptions rasterizerOptions , Point destinationOffset , List < CompositionCommand > commands )
272+ public sealed class CapturedCoverageDefinition
278273 {
279- public IPath SourcePath { get ; } = SourcePath ;
274+ public CapturedCoverageDefinition (
275+ IPath sourcePath ,
276+ RasterizerOptions rasterizerOptions ,
277+ Point destinationOffset ,
278+ List < CompositionCommand > commands )
279+ {
280+ this . SourcePath = sourcePath ;
281+ this . RasterizerOptions = rasterizerOptions ;
282+ this . DestinationOffset = destinationOffset ;
283+ this . Commands = commands ;
284+ }
285+
286+ public IPath SourcePath { get ; }
280287
281- public RasterizerOptions RasterizerOptions { get ; } = rasterizerOptions ;
288+ public RasterizerOptions RasterizerOptions { get ; }
282289
283- public Point DestinationOffset { get ; } = destinationOffset ;
290+ public Point DestinationOffset { get ; }
284291
285- public List < CompositionCommand > Commands { get ; } = commands ;
292+ public List < CompositionCommand > Commands { get ; }
286293 }
287294
288295 private readonly struct CoverageDefinitionKey : IEquatable < CoverageDefinitionKey >
289296 {
290- private readonly int SourcePathIdentity ;
297+ private readonly int sourcePathIdentity ;
291298 private readonly Rectangle interest ;
292299 private readonly IntersectionRule intersectionRule ;
293300 private readonly RasterizationMode rasterizationMode ;
@@ -296,7 +303,7 @@ public sealed class CapturedCoverageDefinition(IPath SourcePath, RasterizerOptio
296303
297304 public CoverageDefinitionKey ( CompositionCommand command )
298305 {
299- this . SourcePathIdentity = RuntimeHelpers . GetHashCode ( command . SourcePath ! ) ;
306+ this . sourcePathIdentity = RuntimeHelpers . GetHashCode ( command . SourcePath ) ;
300307 this . interest = command . RasterizerOptions . Interest ;
301308 this . intersectionRule = command . RasterizerOptions . IntersectionRule ;
302309 this . rasterizationMode = command . RasterizerOptions . RasterizationMode ;
@@ -305,19 +312,19 @@ public CoverageDefinitionKey(CompositionCommand command)
305312 }
306313
307314 public bool Equals ( CoverageDefinitionKey other )
308- => this . SourcePathIdentity == other . SourcePathIdentity &&
315+ => this . sourcePathIdentity == other . sourcePathIdentity &&
309316 this . interest . Equals ( other . interest ) &&
310317 this . intersectionRule == other . intersectionRule &&
311318 this . rasterizationMode == other . rasterizationMode &&
312319 this . samplingOrigin == other . samplingOrigin &&
313320 this . antialiasThresholdBits == other . antialiasThresholdBits ;
314321
315- public override bool Equals ( object ? obj )
322+ public override bool Equals ( object obj )
316323 => obj is CoverageDefinitionKey other && this . Equals ( other ) ;
317324
318325 public override int GetHashCode ( )
319326 => HashCode . Combine (
320- this . SourcePathIdentity ,
327+ this . sourcePathIdentity ,
321328 this . interest ,
322329 ( int ) this . intersectionRule ,
323330 ( int ) this . rasterizationMode ,
0 commit comments