| // 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:html' as html; |
| 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' hide TextStyle; |
| |
| import 'package:web_engine_tester/golden_tester.dart'; |
| |
| void main() { |
| internalBootstrapBrowserTest(() => testMain); |
| } |
| |
| Future<void> testMain() async { |
| const double screenWidth = 600.0; |
| const double screenHeight = 800.0; |
| const Rect screenRect = Rect.fromLTWH(0, 0, screenWidth, screenHeight); |
| |
| // Commit a recording canvas to a bitmap, and compare with the expected |
| Future<void> _checkScreenshot(RecordingCanvas rc, String fileName, |
| {Rect region = const Rect.fromLTWH(0, 0, 500, 500), |
| double? maxDiffRatePercent}) async { |
| final EngineCanvas engineCanvas = BitmapCanvas(screenRect, |
| RenderStrategy()); |
| rc.endRecording(); |
| rc.apply(engineCanvas, screenRect); |
| |
| // Wrap in <flt-scene> so that our CSS selectors kick in. |
| final html.Element sceneElement = html.Element.tag('flt-scene'); |
| try { |
| sceneElement.append(engineCanvas.rootElement); |
| html.document.body!.append(sceneElement); |
| await matchGoldenFile('$fileName.png', region: region, maxDiffRatePercent: maxDiffRatePercent); |
| } finally { |
| // The page is reused across tests, so remove the element after taking the |
| // Scuba screenshot. |
| sceneElement.remove(); |
| } |
| } |
| |
| setUp(() async { |
| debugEmulateFlutterTesterEnvironment = true; |
| await webOnlyInitializePlatform(); |
| webOnlyFontCollection.debugRegisterTestFonts(); |
| await webOnlyFontCollection.ensureFontsLoaded(); |
| }); |
| |
| test('Should draw transformed line.', () async { |
| final RecordingCanvas rc = |
| RecordingCanvas(const Rect.fromLTRB(0, 0, 500, 500)); |
| final Path path = Path(); |
| path.moveTo(0, 0); |
| path.lineTo(300, 200); |
| rc.drawPath( |
| path, |
| SurfacePaint() |
| ..style = PaintingStyle.stroke |
| ..strokeWidth = 2.0 |
| ..color = const Color(0xFF404000)); |
| final Path transformedPath = Path(); |
| final Matrix4 testMatrixTranslateRotate = |
| Matrix4.rotationZ(math.pi * 30.0 / 180.0)..translate(100, 20); |
| transformedPath.addPath(path, Offset.zero, |
| matrix4: testMatrixTranslateRotate.toFloat64()); |
| rc.drawPath( |
| transformedPath, |
| SurfacePaint() |
| ..style = PaintingStyle.stroke |
| ..strokeWidth = 2.0 |
| ..color = const Color.fromRGBO(0, 128, 255, 1.0)); |
| await _checkScreenshot(rc, 'path_transform_with_line'); |
| }); |
| |
| test('Should draw transformed line.', () async { |
| final RecordingCanvas rc = |
| RecordingCanvas(const Rect.fromLTRB(0, 0, 500, 500)); |
| final Path path = Path(); |
| path.addRect(const Rect.fromLTRB(50, 40, 300, 100)); |
| rc.drawPath( |
| path, |
| SurfacePaint() |
| ..style = PaintingStyle.stroke |
| ..strokeWidth = 2.0 |
| ..color = const Color(0xFF404000)); |
| final Path transformedPath = Path(); |
| final Matrix4 testMatrixTranslateRotate = |
| Matrix4.rotationZ(math.pi * 30.0 / 180.0)..translate(100, 20); |
| transformedPath.addPath(path, Offset.zero, |
| matrix4: testMatrixTranslateRotate.toFloat64()); |
| rc.drawPath( |
| transformedPath, |
| SurfacePaint() |
| ..style = PaintingStyle.stroke |
| ..strokeWidth = 2.0 |
| ..color = const Color.fromRGBO(0, 128, 255, 1.0)); |
| await _checkScreenshot(rc, 'path_transform_with_rect'); |
| }); |
| |
| test('Should draw transformed quadratic curve.', () async { |
| final RecordingCanvas rc = |
| RecordingCanvas(const Rect.fromLTRB(0, 0, 500, 500)); |
| final Path path = Path(); |
| path.moveTo(100, 100); |
| path.quadraticBezierTo(100, 300, 400, 300); |
| rc.drawPath( |
| path, |
| SurfacePaint() |
| ..style = PaintingStyle.stroke |
| ..strokeWidth = 2.0 |
| ..color = const Color(0xFF404000)); |
| final Path transformedPath = Path(); |
| final Matrix4 testMatrixTranslateRotate = |
| Matrix4.rotationZ(math.pi * 30.0 / 180.0)..translate(100, -80); |
| transformedPath.addPath(path, Offset.zero, |
| matrix4: testMatrixTranslateRotate.toFloat64()); |
| rc.drawPath( |
| transformedPath, |
| SurfacePaint() |
| ..style = PaintingStyle.stroke |
| ..strokeWidth = 2.0 |
| ..color = const Color.fromRGBO(0, 128, 255, 1.0)); |
| await _checkScreenshot(rc, 'path_transform_with_quadratic_curve'); |
| }); |
| |
| test('Should draw transformed conic.', () async { |
| final RecordingCanvas rc = |
| RecordingCanvas(const Rect.fromLTRB(0, 0, 500, 500)); |
| const double yStart = 20; |
| |
| const Offset p0 = Offset(25, yStart + 25); |
| const Offset pc = Offset(60, yStart + 150); |
| const Offset p2 = Offset(100, yStart + 50); |
| |
| final Path path = Path(); |
| path.moveTo(p0.dx, p0.dy); |
| path.conicTo(pc.dx, pc.dy, p2.dx, p2.dy, 0.5); |
| path.close(); |
| path.moveTo(p0.dx, p0.dy + 100); |
| path.conicTo(pc.dx, pc.dy + 100, p2.dx, p2.dy + 100, 10); |
| path.close(); |
| |
| rc.drawPath( |
| path, |
| SurfacePaint() |
| ..style = PaintingStyle.stroke |
| ..strokeWidth = 2.0 |
| ..color = const Color(0xFF404000)); |
| final Path transformedPath = Path(); |
| final Matrix4 testMatrixTranslateRotate = |
| Matrix4.rotationZ(math.pi * 30.0 / 180.0)..translate(100, -80); |
| transformedPath.addPath(path, Offset.zero, |
| matrix4: testMatrixTranslateRotate.toFloat64()); |
| rc.drawPath( |
| transformedPath, |
| SurfacePaint() |
| ..style = PaintingStyle.stroke |
| ..strokeWidth = 2.0 |
| ..color = const Color.fromRGBO(0, 128, 255, 1.0)); |
| await _checkScreenshot(rc, 'path_transform_with_conic'); |
| }); |
| |
| test('Should draw transformed arc.', () async { |
| final RecordingCanvas rc = |
| RecordingCanvas(const Rect.fromLTRB(0, 0, 500, 500)); |
| |
| final Path path = Path(); |
| path.moveTo(350, 280); |
| path.arcToPoint(const Offset(450, 90), |
| radius: const Radius.elliptical(200, 50), |
| rotation: -math.pi / 6.0, |
| largeArc: true, |
| clockwise: true); |
| path.close(); |
| |
| rc.drawPath( |
| path, |
| SurfacePaint() |
| ..style = PaintingStyle.stroke |
| ..strokeWidth = 2.0 |
| ..color = const Color(0xFF404000)); |
| |
| final Path transformedPath = Path(); |
| final Matrix4 testMatrixTranslateRotate = |
| Matrix4.rotationZ(math.pi * 30.0 / 180.0)..translate(100, 10); |
| transformedPath.addPath(path, Offset.zero, |
| matrix4: testMatrixTranslateRotate.toFloat64()); |
| rc.drawPath( |
| transformedPath, |
| SurfacePaint() |
| ..style = PaintingStyle.stroke |
| ..strokeWidth = 2.0 |
| ..color = const Color.fromRGBO(0, 128, 255, 1.0)); |
| await _checkScreenshot(rc, 'path_transform_with_arc', |
| maxDiffRatePercent: 1.4); |
| }); |
| |
| test('Should draw transformed rrect.', () async { |
| final RecordingCanvas rc = |
| RecordingCanvas(const Rect.fromLTRB(0, 0, 500, 500)); |
| |
| final Path path = Path(); |
| path.addRRect(RRect.fromLTRBR(50, 50, 300, 200, const Radius.elliptical(4, 8))); |
| |
| rc.drawPath( |
| path, |
| SurfacePaint() |
| ..style = PaintingStyle.stroke |
| ..strokeWidth = 2.0 |
| ..color = const Color(0xFF404000)); |
| |
| final Path transformedPath = Path(); |
| final Matrix4 testMatrixTranslateRotate = |
| Matrix4.rotationZ(math.pi * 30.0 / 180.0)..translate(100, -80); |
| transformedPath.addPath(path, Offset.zero, |
| matrix4: testMatrixTranslateRotate.toFloat64()); |
| rc.drawPath( |
| transformedPath, |
| SurfacePaint() |
| ..style = PaintingStyle.stroke |
| ..strokeWidth = 2.0 |
| ..color = const Color.fromRGBO(0, 128, 255, 1.0)); |
| await _checkScreenshot(rc, 'path_transform_with_rrect'); |
| }); |
| } |