@@ -18,35 +18,19 @@ void main() {
1818}
1919
2020abstract class TestCodec {
21- TestCodec ({required this .description});
22- final String description;
23-
24- ui.Codec ? _cachedCodec;
25-
26- Future <ui.Codec > getCodec () async => _cachedCodec ?? = await createCodec ();
27-
28- Future <ui.Codec > createCodec ();
29-
30- void dispose () {
31- _cachedCodec? .dispose ();
32- _cachedCodec = null ;
33- }
34- }
35-
36- abstract class TestFileCodec extends TestCodec {
37- TestFileCodec .fromTestFile (this .testFile, {required super .description});
21+ TestCodec .fromTestFile (this .testFile, {required this .description});
3822
3923 final String testFile;
24+ final String description;
4025
4126 Future <ui.Codec > createCodecFromTestFile (String testFile);
4227
43- @override
4428 Future <ui.Codec > createCodec () {
4529 return createCodecFromTestFile (testFile);
4630 }
4731}
4832
49- class UrlTestCodec extends TestFileCodec {
33+ class UrlTestCodec extends TestCodec {
5034 UrlTestCodec (super .testFile, this .codecFactory, String function)
5135 : super .fromTestFile (description: 'created with $function ("$testFile ")' );
5236
@@ -58,7 +42,7 @@ class UrlTestCodec extends TestFileCodec {
5842 }
5943}
6044
61- class FetchTestCodec extends TestFileCodec {
45+ class FetchTestCodec extends TestCodec {
6246 FetchTestCodec (super .testFile, this .codecFactory, String function)
6347 : super .fromTestFile (
6448 description:
@@ -70,7 +54,7 @@ class FetchTestCodec extends TestFileCodec {
7054
7155 @override
7256 Future <ui.Codec > createCodecFromTestFile (String testFile) async {
73- final HttpFetchResponse response = await httpFetch (testFile);
57+ final HttpFetchResponse response = await httpFetch ('/test_images/$ testFile ' );
7458
7559 if (! response.hasPayload) {
7660 throw Exception ('Unable to fetch() image test file "$testFile "' );
@@ -81,7 +65,7 @@ class FetchTestCodec extends TestFileCodec {
8165 }
8266}
8367
84- class BitmapTestCodec extends TestFileCodec {
68+ class BitmapTestCodec extends TestCodec {
8569 BitmapTestCodec (super .testFile, this .codecFactory, String function)
8670 : super .fromTestFile (
8771 description:
@@ -94,7 +78,7 @@ class BitmapTestCodec extends TestFileCodec {
9478 @override
9579 Future <ui.Codec > createCodecFromTestFile (String testFile) async {
9680 final DomHTMLImageElement imageElement = createDomHTMLImageElement ();
97- imageElement.src = testFile;
81+ imageElement.src = '/test_images/$ testFile ' ;
9882 imageElement.decoding = 'async' ;
9983
10084 await imageElement.decode ();
@@ -168,26 +152,25 @@ Future<void> testMain() async {
168152 );
169153 testCodecs.add (
170154 FetchTestCodec (
171- '/test_images/$ testFile ' ,
155+ testFile,
172156 (Uint8List bytes) => renderer.instantiateImageCodec (bytes),
173157 'renderer.instantiateImageCodec' ,
174158 ),
175159 );
176160 testCodecs.add (
177161 FetchTestCodec (
178- '/test_images/$ testFile ' ,
162+ testFile,
179163 (Uint8List bytes) => renderer.instantiateImageCodec (
180164 bytes,
181165 targetWidth: testTargetWidth,
182166 targetHeight: testTargetHeight,
183167 ),
184- 'renderer.instantiateImageCodec '
185- '($testTargetWidth x $testTargetHeight )' ,
168+ 'renderer.instantiateImageCodec ($testTargetWidth x $testTargetHeight )' ,
186169 ),
187170 );
188171 testCodecs.add (
189172 BitmapTestCodec (
190- 'test_images/$ testFile ' ,
173+ testFile,
191174 (DomImageBitmap bitmap) async => renderer.createImageFromImageBitmap (bitmap),
192175 'renderer.createImageFromImageBitmap' ,
193176 ),
@@ -204,33 +187,47 @@ Future<void> testMain() async {
204187 mockHttpFetchResponseFactory = null ;
205188 });
206189
207- group ('Codecs' , () {
208- final List <TestCodec > testCodecs = createTestCodecs ();
209- for (final TestCodec testCodec in testCodecs) {
210- test ('${testCodec .description } can create an image' , () async {
211- try {
212- final ui.Codec codec = await testCodec.getCodec ();
213- final ui.FrameInfo frameInfo = await codec.getNextFrame ();
214- final ui.Image image = frameInfo.image;
215- expect (image, isNotNull);
216- expect (image.width, isNonZero);
217- expect (image.height, isNonZero);
218- expect (image.colorSpace, isNotNull);
219- } catch (e) {
220- throw TestFailure ('Failed to get image for ${testCodec .description }: $e ' );
190+ void runCodecTest (TestCodec testCodec) {
191+ const problematicChromeImages = < String , Set <int >> {
192+ // Frame 2 cause Chrome to crash.
193+ // https://issues.chromium.org/456445108
194+ 'crbug445556737.png' : {2 },
195+ // Frames 2 and 3 cause Chrome to crash.
196+ // https://issues.chromium.org/456445108
197+ 'interlaced-multiframe-with-blending.png' : {2 , 3 },
198+ };
199+
200+ test ('${testCodec .description } can create an image and convert it to byte array' , () async {
201+ final ui.Codec codec = await testCodec.createCodec ();
202+
203+ final Set <int > problematicFrames;
204+ if (isChromium && problematicChromeImages.containsKey (testCodec.testFile)) {
205+ // Encountered an image with known problematic frames on Chromium.
206+ problematicFrames = problematicChromeImages[testCodec.testFile]! ;
207+ } else {
208+ problematicFrames = < int > {};
209+ }
210+
211+ for (int i = 0 ; i < codec.frameCount; i++ ) {
212+ if (problematicFrames.contains (i)) {
213+ printWarning (
214+ 'Skipping frame $i of ${testCodec .description } due to known Chromium crash bug.' ,
215+ );
216+ continue ;
221217 }
222- });
223218
224- test ('${testCodec .description } can be decoded with toByteData' , () async {
225- ui.Image image;
219+ final ui.Image image;
226220 try {
227- final ui.Codec codec = await testCodec.getCodec ();
228221 final ui.FrameInfo frameInfo = await codec.getNextFrame ();
229222 image = frameInfo.image;
230223 } catch (e) {
231- throw TestFailure ('Failed to get image for ${testCodec .description }: $e ' );
224+ codec.dispose ();
225+ throw TestFailure ('Failed to get image at frame $i for ${testCodec .description }: $e ' );
232226 }
233227
228+ expect (image.width, isNonZero);
229+ expect (image.height, isNonZero);
230+
234231 final ByteData ? byteData = await image.toByteData ();
235232 expect (
236233 byteData,
@@ -249,12 +246,31 @@ Future<void> testMain() async {
249246 '${testCodec .description } toByteData() should '
250247 'contain nonzero value' ,
251248 );
252- });
253- }
254- for (final testCodec in testCodecs) {
255- testCodec.dispose ();
256- }
249+ }
250+
251+ // After all frames are decoded and tested, dispose the codec.
252+ codec.dispose ();
253+ });
254+ }
255+
256+ group ('Codecs (default browserSupportsImageDecoder)' , () {
257+ createTestCodecs ().forEach (runCodecTest);
257258 });
259+
260+ if (browserSupportsImageDecoder) {
261+ // For the sake of completeness, test codec fallback logic on browsers that support
262+ // `ImageDecoder`.
263+ group ('Codecs (browserSupportsImageDecoder=false)' , () {
264+ setUpAll (() {
265+ browserSupportsImageDecoder = false ;
266+ });
267+ tearDownAll (() {
268+ debugResetBrowserSupportsImageDecoder ();
269+ });
270+
271+ createTestCodecs ().forEach (runCodecTest);
272+ });
273+ }
258274 });
259275
260276 test ('crossOrigin requests cause an error' , () async {
0 commit comments