diff --git a/lib/web_ui/test/ui/canvas_lines_golden_test.dart b/lib/web_ui/test/ui/canvas_lines_golden_test.dart new file mode 100644 index 0000000000000..c1ea41b09037a --- /dev/null +++ b/lib/web_ui/test/ui/canvas_lines_golden_test.dart @@ -0,0 +1,141 @@ +// 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 'package:test/bootstrap/browser.dart'; +import 'package:test/test.dart'; +import 'package:ui/ui.dart'; + +import 'utils.dart'; + +void main() { + internalBootstrapBrowserTest(() => testMain); +} + +Future testMain() async { + setUpUiTest(); + + const Rect region = Rect.fromLTWH(0, 0, 300, 300); + + test('draws lines with varying strokeWidth', () async { + final PictureRecorder recorder = PictureRecorder(); + final Canvas canvas = Canvas(recorder, region); + paintLines(canvas); + + drawPictureUsingCurrentRenderer(recorder.endRecording()); + + await matchGolden('canvas_lines_thickness.png', region: region); + }); + + test('draws lines with negative Offset values', () async { + final PictureRecorder recorder = PictureRecorder(); + final Canvas canvas = Canvas(recorder, region); + + // test rendering lines correctly with negative offset when using DOM + final Paint paintWithStyle = Paint() + ..color = const Color(0xFFE91E63) // Colors.pink + ..style = PaintingStyle.stroke + ..strokeWidth = 16 + ..strokeCap = StrokeCap.round; + + // canvas.drawLine ignores paint.style (defaults to fill) according to api docs. + // expect lines are rendered the same regardless of the set paint.style + final Paint paintWithoutStyle = Paint() + ..color = const Color(0xFF4CAF50) // Colors.green + ..strokeWidth = 16 + ..strokeCap = StrokeCap.round; + + // test vertical, horizontal, and diagonal lines + final List points = [ + const Offset(-25, 50), const Offset(45, 50), + const Offset(100, -25), const Offset(100, 200), + const Offset(-150, -145), const Offset(100, 200), + ]; + final List shiftedPoints = points.map((Offset point) => point.translate(20, 20)).toList(); + + paintLinesFromPoints(canvas, paintWithStyle, points); + paintLinesFromPoints(canvas, paintWithoutStyle, shiftedPoints); + + drawPictureUsingCurrentRenderer(recorder.endRecording()); + await matchGolden('canvas_lines_with_negative_offset.png', region: region); + }); + + test('drawLines method respects strokeCap', () async { + final PictureRecorder recorder = PictureRecorder(); + final Canvas canvas = Canvas(recorder, region); + + final Paint paintStrokeCapRound = Paint() + ..color = const Color(0xFFE91E63) // Colors.pink + ..strokeWidth = 16 + ..strokeCap = StrokeCap.round; + + final Paint paintStrokeCapSquare = Paint() + ..color = const Color(0xFF4CAF50) // Colors.green + ..strokeWidth = 16 + ..strokeCap = StrokeCap.square; + + final Paint paintStrokeCapButt = Paint() + ..color = const Color(0xFFFF9800) // Colors.orange + ..strokeWidth = 16 + ..strokeCap = StrokeCap.butt; + + // test vertical, horizontal, and diagonal lines + final List points = [ + const Offset(5, 50), const Offset(45, 50), + const Offset(100, 5), const Offset(100, 200), + const Offset(5, 10), const Offset(100, 200), + ]; + final List shiftedPoints = points.map((Offset point) => point.translate(50, 50)).toList(); + final List twiceShiftedPoints = shiftedPoints.map((Offset point) => point.translate(50, 50)).toList(); + + paintLinesFromPoints(canvas, paintStrokeCapRound, points); + paintLinesFromPoints(canvas, paintStrokeCapSquare, shiftedPoints); + paintLinesFromPoints(canvas, paintStrokeCapButt, twiceShiftedPoints); + + drawPictureUsingCurrentRenderer(recorder.endRecording()); + await matchGolden('canvas_lines_with_strokeCap.png', region: region); + }); +} + +void paintLines(Canvas canvas) { + final Paint nullPaint = Paint() + ..strokeWidth = 1.0 + ..style = PaintingStyle.stroke; + final Paint paint1 = Paint() + ..color = const Color(0xFF9E9E9E) // Colors.grey + ..strokeWidth = 1.0 + ..style = PaintingStyle.stroke; + final Paint paint2 = Paint() + ..color = const Color(0x7fff0000) + ..strokeWidth = 1.0 + ..style = PaintingStyle.stroke; + final Paint paint3 = Paint() + ..color = const Color(0xFF4CAF50) //Colors.green + ..strokeWidth = 1.0 + ..style = PaintingStyle.stroke; + // Draw markers around 100x100 box + canvas.drawLine(const Offset(50, 40), const Offset(148, 40), nullPaint); + canvas.drawLine(const Offset(50, 50), const Offset(52, 50), paint1); + canvas.drawLine(const Offset(150, 50), const Offset(148, 50), paint1); + canvas.drawLine(const Offset(50, 150), const Offset(52, 150), paint1); + canvas.drawLine(const Offset(150, 150), const Offset(148, 150), paint1); + // Draw diagonal + canvas.drawLine(const Offset(50, 50), const Offset(150, 150), paint2); + // Draw horizontal + paint3.strokeWidth = 1.0; + paint3.color = const Color(0xFFFF0000); + canvas.drawLine(const Offset(50, 55), const Offset(150, 55), paint3); + paint3.strokeWidth = 2.0; + paint3.color = const Color(0xFF2196F3); // Colors.blue; + canvas.drawLine(const Offset(50, 60), const Offset(150, 60), paint3); + paint3.strokeWidth = 4.0; + paint3.color = const Color(0xFFFF9800); // Colors.orange; + canvas.drawLine(const Offset(50, 70), const Offset(150, 70), paint3); +} + +void paintLinesFromPoints(Canvas canvas, Paint paint, List points) { + // points list contains pairs of Offset points, so for loop step is 2 + for (int i = 0; i < points.length - 1; i += 2) { + canvas.drawLine(points[i], points[i + 1], paint); + } +} diff --git a/lib/web_ui/test/ui/utils.dart b/lib/web_ui/test/ui/utils.dart index da6c5ffb720d7..b44179c0e25e0 100644 --- a/lib/web_ui/test/ui/utils.dart +++ b/lib/web_ui/test/ui/utils.dart @@ -2,17 +2,39 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:test/test.dart'; import 'package:ui/src/engine.dart'; +import 'package:ui/ui.dart'; +import 'package:web_engine_tester/golden_tester.dart'; import '../canvaskit/common.dart'; +// TODO(hterkelsen): Support skwasm. + /// Initializes the renderer for this test. void setUpUiTest() { - if (renderer is CanvasKitRenderer) { + setUpAll(() async { + await webOnlyInitializePlatform(); + await renderer.fontCollection.debugDownloadTestFonts(); + renderer.fontCollection.registerDownloadedFonts(); + }); + if (isCanvasKit) { setUpCanvasKitTest(); } } +/// Draws the [Picture]. This is in preparation for a golden test. +void drawPictureUsingCurrentRenderer(Picture picture) { + final SceneBuilder sb = SceneBuilder(); + sb.pushOffset(0, 0); + sb.addPicture(Offset.zero, picture); + renderer.renderScene(sb.build()); +} + +Future matchGolden(String basename, {Rect? region}) async { + await matchGoldenFile('canvas_lines_thickness.png', region: region); +} + /// Returns [true] if this test is running in the CanvasKit renderer. bool get isCanvasKit => renderer is CanvasKitRenderer;