| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'dart:math' as math; |
| |
| import 'package:test/bootstrap/browser.dart'; |
| import 'package:test/test.dart'; |
| import 'package:ui/src/engine.dart'; |
| import 'package:ui/ui.dart' as ui; |
| import 'package:web_engine_tester/golden_tester.dart'; |
| |
| import '../common/rendering.dart'; |
| import '../common/test_initialization.dart'; |
| import 'utils.dart'; |
| |
| void main() { |
| internalBootstrapBrowserTest(() => testMain); |
| } |
| |
| Future<void> testMain() async { |
| setUpUnitTests( |
| emulateTesterEnvironment: false, |
| setUpTestViewDimensions: false, |
| ); |
| |
| group('${ui.SceneBuilder}', () { |
| const ui.Rect region = ui.Rect.fromLTWH(0, 0, 300, 300); |
| test('Test offset layer', () async { |
| final ui.SceneBuilder sceneBuilder = ui.SceneBuilder(); |
| sceneBuilder.pushOffset(150, 150); |
| sceneBuilder.addPicture(ui.Offset.zero, drawPicture((ui.Canvas canvas) { |
| canvas.drawCircle( |
| ui.Offset.zero, |
| 50, |
| ui.Paint()..color = const ui.Color(0xFF00FF00) |
| ); |
| })); |
| |
| await renderScene(sceneBuilder.build()); |
| await matchGoldenFile('scene_builder_centered_circle.png', region: region); |
| }); |
| |
| test('Test transform layer', () async { |
| final ui.SceneBuilder sceneBuilder = ui.SceneBuilder(); |
| final Matrix4 transform = Matrix4.identity(); |
| |
| // The html renderer expects the top-level transform to just be a scaling |
| // matrix for the device pixel ratio, so just push the identity matrix. |
| sceneBuilder.pushTransform(transform.toFloat64()); |
| transform.translate(150, 150); |
| transform.rotate(kUnitZ, math.pi / 3); |
| sceneBuilder.pushTransform(transform.toFloat64()); |
| sceneBuilder.addPicture(ui.Offset.zero, drawPicture((ui.Canvas canvas) { |
| canvas.drawRRect( |
| ui.RRect.fromRectAndRadius( |
| ui.Rect.fromCircle(center: ui.Offset.zero, radius: 50), |
| const ui.Radius.circular(10) |
| ), |
| ui.Paint()..color = const ui.Color(0xFF0000FF) |
| ); |
| })); |
| |
| await renderScene(sceneBuilder.build()); |
| await matchGoldenFile('scene_builder_rotated_rounded_square.png', region: region); |
| }); |
| |
| test('Test clipRect layer', () async { |
| final ui.SceneBuilder sceneBuilder = ui.SceneBuilder(); |
| sceneBuilder.pushClipRect(const ui.Rect.fromLTRB(0, 0, 150, 150)); |
| sceneBuilder.addPicture(ui.Offset.zero, drawPicture((ui.Canvas canvas) { |
| canvas.drawCircle( |
| const ui.Offset(150, 150), |
| 50, |
| ui.Paint()..color = const ui.Color(0xFFFF0000) |
| ); |
| })); |
| |
| await renderScene(sceneBuilder.build()); |
| await matchGoldenFile('scene_builder_circle_clip_rect.png', region: region); |
| }); |
| |
| test('Test clipRRect layer', () async { |
| final ui.SceneBuilder sceneBuilder = ui.SceneBuilder(); |
| sceneBuilder.pushClipRRect(ui.RRect.fromRectAndRadius( |
| const ui.Rect.fromLTRB(0, 0, 150, 150), |
| const ui.Radius.circular(25), |
| ), clipBehavior: ui.Clip.antiAlias); |
| sceneBuilder.addPicture(ui.Offset.zero, drawPicture((ui.Canvas canvas) { |
| canvas.drawCircle( |
| const ui.Offset(150, 150), |
| 50, |
| ui.Paint()..color = const ui.Color(0xFFFF00FF) |
| ); |
| })); |
| |
| await renderScene(sceneBuilder.build()); |
| await matchGoldenFile('scene_builder_circle_clip_rrect.png', region: region); |
| }); |
| |
| test('Test clipPath layer', () async { |
| final ui.SceneBuilder sceneBuilder = ui.SceneBuilder(); |
| final ui.Path path = ui.Path(); |
| path.addOval(ui.Rect.fromCircle(center: const ui.Offset(150, 150), radius: 60)); |
| sceneBuilder.pushClipPath(path); |
| sceneBuilder.addPicture(ui.Offset.zero, drawPicture((ui.Canvas canvas) { |
| canvas.drawRect( |
| ui.Rect.fromCircle(center: const ui.Offset(150, 150), radius: 50), |
| ui.Paint()..color = const ui.Color(0xFF00FFFF) |
| ); |
| })); |
| |
| await renderScene(sceneBuilder.build()); |
| await matchGoldenFile('scene_builder_rectangle_clip_circular_path.png', region: region); |
| }); |
| |
| test('Test opacity layer', () async { |
| final ui.SceneBuilder sceneBuilder = ui.SceneBuilder(); |
| sceneBuilder.addPicture(ui.Offset.zero, drawPicture((ui.Canvas canvas) { |
| canvas.drawRect( |
| ui.Rect.fromCircle(center: const ui.Offset(150, 150), radius: 50), |
| ui.Paint()..color = const ui.Color(0xFF00FF00) |
| ); |
| })); |
| |
| sceneBuilder.pushOpacity(0x7F); |
| sceneBuilder.addPicture(ui.Offset.zero, drawPicture((ui.Canvas canvas) { |
| final ui.Paint paint = ui.Paint()..color = const ui.Color(0xFFFF0000); |
| canvas.drawCircle( |
| const ui.Offset(125, 150), |
| 50, |
| paint |
| ); |
| canvas.drawCircle( |
| const ui.Offset(175, 150), |
| 50, |
| paint |
| ); |
| })); |
| |
| await renderScene(sceneBuilder.build()); |
| await matchGoldenFile('scene_builder_opacity_circles_on_square.png', region: region); |
| }); |
| |
| test('shader mask layer', () async { |
| final ui.SceneBuilder sceneBuilder = ui.SceneBuilder(); |
| |
| sceneBuilder.addPicture(ui.Offset.zero, drawPicture((ui.Canvas canvas) { |
| final ui.Paint paint = ui.Paint()..color = const ui.Color(0xFFFF0000); |
| canvas.drawCircle( |
| const ui.Offset(125, 150), |
| 50, |
| paint |
| ); |
| canvas.drawCircle( |
| const ui.Offset(175, 150), |
| 50, |
| paint |
| ); |
| })); |
| |
| final ui.Shader shader = ui.Gradient.linear( |
| ui.Offset.zero, |
| const ui.Offset(50, 50), <ui.Color>[ |
| const ui.Color(0xFFFFFFFF), |
| const ui.Color(0x00000000), |
| ]); |
| sceneBuilder.pushShaderMask( |
| shader, |
| const ui.Rect.fromLTRB(125, 125, 175, 175), |
| ui.BlendMode.srcATop |
| ); |
| |
| sceneBuilder.addPicture(ui.Offset.zero, drawPicture((ui.Canvas canvas) { |
| canvas.drawRect( |
| ui.Rect.fromCircle(center: const ui.Offset(150, 150), radius: 50), |
| ui.Paint()..color = const ui.Color(0xFF00FF00) |
| ); |
| })); |
| |
| await renderScene(sceneBuilder.build()); |
| await matchGoldenFile('scene_builder_shader_mask.png', region: region); |
| }, skip: isFirefox && isHtml); // https://github.com/flutter/flutter/issues/86623 |
| |
| test('backdrop filter layer', () async { |
| final ui.SceneBuilder sceneBuilder = ui.SceneBuilder(); |
| |
| sceneBuilder.addPicture(ui.Offset.zero, drawPicture((ui.Canvas canvas) { |
| // Create a red and blue checkerboard pattern |
| final ui.Paint redPaint = ui.Paint()..color = const ui.Color(0xFFFF0000); |
| final ui.Paint bluePaint = ui.Paint()..color = const ui.Color(0xFF0000FF); |
| for (double y = 0; y < 300; y += 10) { |
| for (double x = 0; x < 300; x += 10) { |
| final ui.Paint paint = ((x + y) % 20 == 0) ? redPaint : bluePaint; |
| canvas.drawRect(ui.Rect.fromLTWH(x, y, 10, 10), paint); |
| } |
| } |
| })); |
| |
| sceneBuilder.pushBackdropFilter(ui.ImageFilter.blur( |
| sigmaX: 3.0, |
| sigmaY: 3.0, |
| )); |
| |
| sceneBuilder.addPicture(ui.Offset.zero, drawPicture((ui.Canvas canvas) { |
| canvas.drawCircle( |
| const ui.Offset(150, 150), |
| 50, |
| ui.Paint()..color = const ui.Color(0xFF00FF00) |
| ); |
| })); |
| |
| await renderScene(sceneBuilder.build()); |
| await matchGoldenFile('scene_builder_backdrop_filter.png', region: region); |
| }); |
| |
| test('image filter layer', () async { |
| final ui.SceneBuilder sceneBuilder = ui.SceneBuilder(); |
| sceneBuilder.pushImageFilter(ui.ImageFilter.blur( |
| sigmaX: 5.0, |
| sigmaY: 5.0, |
| )); |
| |
| sceneBuilder.addPicture(ui.Offset.zero, drawPicture((ui.Canvas canvas) { |
| canvas.drawCircle( |
| const ui.Offset(150, 150), |
| 50, |
| ui.Paint()..color = const ui.Color(0xFF00FF00) |
| ); |
| })); |
| |
| await renderScene(sceneBuilder.build()); |
| await matchGoldenFile('scene_builder_image_filter.png', region: region); |
| }); |
| |
| test('color filter layer', () async { |
| final ui.SceneBuilder sceneBuilder = ui.SceneBuilder(); |
| const ui.ColorFilter sepia = ui.ColorFilter.matrix(<double>[ |
| 0.393, 0.769, 0.189, 0, 0, |
| 0.349, 0.686, 0.168, 0, 0, |
| 0.272, 0.534, 0.131, 0, 0, |
| 0, 0, 0, 1, 0, |
| ]); |
| sceneBuilder.pushColorFilter(sepia); |
| |
| sceneBuilder.addPicture(ui.Offset.zero, drawPicture((ui.Canvas canvas) { |
| canvas.drawCircle( |
| const ui.Offset(150, 150), |
| 50, |
| ui.Paint()..color = const ui.Color(0xFF00FF00) |
| ); |
| })); |
| |
| await renderScene(sceneBuilder.build()); |
| await matchGoldenFile('scene_builder_color_filter.png', region: region); |
| }); |
| }); |
| } |
| |
| ui.Picture drawPicture(void Function(ui.Canvas) drawCommands) { |
| final ui.PictureRecorder recorder = ui.PictureRecorder(); |
| final ui.Canvas canvas = ui.Canvas(recorder); |
| drawCommands(canvas); |
| return recorder.endRecording(); |
| } |