@@ -86,17 +86,23 @@ Future<void> testMain() async {
8686 // `imageGenerator` should produce an image that is 150x150 pixels.
8787 void emitImageTests (String name, Future <ui.Image > Function () imageGenerator) {
8888 group (name, () {
89- late ui.Image image;
90- setUp (() async {
91- image = await imageGenerator ();
92- });
89+ final List <ui.Image > images = < ui.Image > [];
90+
91+ Future <ui.Image > generateImage () async {
92+ final ui.Image image = await imageGenerator ();
93+ images.add (image);
94+ return image;
95+ }
9396
9497 tearDown (() {
95- image.dispose ();
98+ for (final ui.Image image in images) {
99+ image.dispose ();
100+ }
101+ images.clear ();
96102 });
97103
98104 test ('drawImage' , () async {
99- final ui.Image image = await imageGenerator ();
105+ final ui.Image image = await generateImage ();
100106
101107 final ui.PictureRecorder recorder = ui.PictureRecorder ();
102108 final ui.Canvas canvas = ui.Canvas (recorder, drawRegion);
@@ -111,7 +117,7 @@ Future<void> testMain() async {
111117 });
112118
113119 test ('drawImageRect' , () async {
114- final ui.Image image = await imageGenerator ();
120+ final ui.Image image = await generateImage ();
115121
116122 final ui.PictureRecorder recorder = ui.PictureRecorder ();
117123 final ui.Canvas canvas = ui.Canvas (recorder, drawRegion);
@@ -147,7 +153,7 @@ Future<void> testMain() async {
147153 });
148154
149155 test ('drawImageNine' , () async {
150- final ui.Image image = await imageGenerator ();
156+ final ui.Image image = await generateImage ();
151157
152158 final ui.PictureRecorder recorder = ui.PictureRecorder ();
153159 final ui.Canvas canvas = ui.Canvas (recorder, drawRegion);
@@ -164,29 +170,42 @@ Future<void> testMain() async {
164170 });
165171
166172 test ('image_shader_cubic_rotated' , () async {
167- final ui.Image image = await imageGenerator ();
168-
169- final Float64List matrix = Matrix4 .rotationZ (pi / 6 ).toFloat64 ();
170- final ui.ImageShader shader = ui.ImageShader (
171- image,
172- ui.TileMode .repeated,
173- ui.TileMode .repeated,
174- matrix,
175- filterQuality: ui.FilterQuality .high,
176- );
177173 final ui.PictureRecorder recorder = ui.PictureRecorder ();
178174 final ui.Canvas canvas = ui.Canvas (recorder, drawRegion);
179- canvas.drawOval (
180- const ui.Rect .fromLTRB (0 , 50 , 300 , 250 ),
181- ui.Paint ()..shader = shader
182- );
175+ final Float64List matrix = Matrix4 .rotationZ (pi / 6 ).toFloat64 ();
176+ Future <void > drawOvalWithShader (ui.Rect rect, ui.FilterQuality quality) async {
177+ final ui.Image image = await generateImage ();
178+ final ui.ImageShader shader = ui.ImageShader (
179+ image,
180+ ui.TileMode .repeated,
181+ ui.TileMode .repeated,
182+ matrix,
183+ filterQuality: quality,
184+ );
185+ canvas.drawOval (
186+ rect,
187+ ui.Paint ()..shader = shader
188+ );
189+ }
190+
191+ // Draw image shader with all four qualities.
192+ await drawOvalWithShader (const ui.Rect .fromLTRB (0 , 0 , 150 , 100 ), ui.FilterQuality .none);
193+ await drawOvalWithShader (const ui.Rect .fromLTRB (150 , 0 , 300 , 100 ), ui.FilterQuality .low);
194+
195+ // Note that for images that skia handles lazily (ones created via
196+ // `createImageFromImageBitmap` or `instantiateImageCodecFromUrl`)
197+ // there is a skia bug that this just renders a black oval instead of
198+ // actually texturing it with the image.
199+ // See https://g-issues.skia.org/issues/338095525
200+ await drawOvalWithShader (const ui.Rect .fromLTRB (0 , 100 , 150 , 200 ), ui.FilterQuality .medium);
201+ await drawOvalWithShader (const ui.Rect .fromLTRB (150 , 100 , 300 , 200 ), ui.FilterQuality .high);
183202
184203 await drawPictureUsingCurrentRenderer (recorder.endRecording ());
185204 await matchGoldenFile ('${name }_image_shader_cubic_rotated.png' , region: drawRegion);
186205 });
187206
188207 test ('fragment_shader_sampler' , () async {
189- final ui.Image image = await imageGenerator ();
208+ final ui.Image image = await generateImage ();
190209
191210 final ui.FragmentProgram program = await renderer.createFragmentProgram ('glitch_shader' );
192211 final ui.FragmentShader shader = program.fragmentShader ();
@@ -210,16 +229,61 @@ Future<void> testMain() async {
210229 await matchGoldenFile ('${name }_fragment_shader_sampler.png' , region: drawRegion);
211230 }, skip: isHtml); // HTML doesn't support fragment shaders
212231
232+ test ('drawVertices with image shader' , () async {
233+ final ui.Image image = await generateImage ();
234+
235+ final Float64List matrix = Matrix4 .rotationZ (pi / 6 ).toFloat64 ();
236+ final ui.ImageShader shader = ui.ImageShader (
237+ image,
238+ ui.TileMode .decal,
239+ ui.TileMode .decal,
240+ matrix,
241+ );
242+
243+ // Draw an octagon
244+ const List <ui.Offset > vertexValues = < ui.Offset > [
245+ ui.Offset (50 , 0 ),
246+ ui.Offset (100 , 0 ),
247+ ui.Offset (150 , 50 ),
248+ ui.Offset (150 , 100 ),
249+ ui.Offset (100 , 150 ),
250+ ui.Offset (50 , 150 ),
251+ ui.Offset (0 , 100 ),
252+ ui.Offset (0 , 50 ),
253+ ];
254+ final ui.Vertices vertices = ui.Vertices (
255+ ui.VertexMode .triangles,
256+ vertexValues,
257+ textureCoordinates: vertexValues,
258+ indices: < int > [
259+ 0 , 1 , 2 , //
260+ 0 , 2 , 3 , //
261+ 0 , 3 , 4 , //
262+ 0 , 4 , 5 , //
263+ 0 , 5 , 6 , //
264+ 0 , 6 , 7 , //
265+ ],
266+ );
267+
268+ final ui.PictureRecorder recorder = ui.PictureRecorder ();
269+ final ui.Canvas canvas = ui.Canvas (recorder, drawRegion);
270+ canvas.drawVertices (vertices, ui.BlendMode .srcOver, ui.Paint ()..shader = shader);
271+
272+ await drawPictureUsingCurrentRenderer (recorder.endRecording ());
273+
274+ await matchGoldenFile ('${name }_drawVertices_imageShader.png' , region: drawRegion);
275+ }, skip: isHtml); // https://github.com/flutter/flutter/issues/127454;
276+
213277 test ('toByteData_rgba' , () async {
214- final ui.Image image = await imageGenerator ();
278+ final ui.Image image = await generateImage ();
215279
216280 final ByteData ? rgbaData = await image.toByteData ();
217281 expect (rgbaData, isNotNull);
218282 expect (rgbaData! .lengthInBytes, isNonZero);
219283 });
220284
221285 test ('toByteData_png' , () async {
222- final ui.Image image = await imageGenerator ();
286+ final ui.Image image = await generateImage ();
223287
224288 final ByteData ? pngData = await image.toByteData (format: ui.ImageByteFormat .png);
225289 expect (pngData, isNotNull);
0 commit comments