| // 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 'dart:typed_data'; |
| |
| import 'package:test/bootstrap/browser.dart'; |
| import 'package:test/test.dart'; |
| import 'package:ui/ui.dart' as ui; |
| import 'package:web_engine_tester/golden_tester.dart'; |
| |
| import '../common/test_initialization.dart'; |
| import 'utils.dart'; |
| |
| void main() { |
| internalBootstrapBrowserTest(() => testMain); |
| } |
| |
| const ui.Rect kBlueSquareRegion = ui.Rect.fromLTRB(0, 0, 25, 25); |
| const ui.Rect kRedCircleRegion = ui.Rect.fromLTRB(25, 0, 50, 25); |
| const ui.Rect kMagentaStarRegion = ui.Rect.fromLTRB(0, 25, 30, 55); |
| const ui.Rect kGreenSquiggleRegion = ui.Rect.fromLTRB(30, 25, 50, 55); |
| const ui.Rect kTotalAtlasRegion = ui.Rect.fromLTRB(0, 0, 55, 55); |
| |
| ui.Image generateAtlas() { |
| final ui.PictureRecorder recorder = ui.PictureRecorder(); |
| final ui.Canvas canvas = ui.Canvas(recorder); |
| |
| canvas.drawColor(const ui.Color(0), ui.BlendMode.src); |
| |
| // Draw the square |
| canvas.save(); |
| canvas.clipRect(kBlueSquareRegion); |
| canvas.drawRect( |
| // Inset the square by one pixel so it doesn't bleed into the other sprites. |
| kBlueSquareRegion.deflate(1.0), |
| ui.Paint()..color = const ui.Color(0xFF0000FF) |
| ); |
| canvas.restore(); |
| |
| // Draw the circle |
| canvas.save(); |
| canvas.clipRect(kRedCircleRegion); |
| canvas.drawCircle( |
| kRedCircleRegion.center, |
| // Make the circle one pixel smaller than the bounds to it doesn't bleed |
| // into the other shapes. |
| (kRedCircleRegion.width / 2.0) - 1.0, |
| ui.Paint()..color = const ui.Color(0xFFFF0000)); |
| canvas.restore(); |
| |
| // Draw the star |
| canvas.save(); |
| canvas.clipRect(kMagentaStarRegion); |
| final ui.Offset starCenter = kMagentaStarRegion.center; |
| |
| // Make the star one pixel smaller than the bounds so that it doesn't bleed |
| // into the other shapes. |
| final double radius = (kMagentaStarRegion.height / 2.0) - 1.0; |
| |
| // Start at the top (rotated 90 degrees) |
| double theta = -math.pi / 2.0; |
| |
| // Rotate two fifths of the circle each time |
| const double rotation = 4.0 * math.pi / 5.0; |
| final ui.Path starPath = ui.Path(); |
| starPath.moveTo( |
| starCenter.dx + radius * math.cos(theta), |
| starCenter.dy + radius * math.sin(theta) |
| ); |
| for (int i = 0; i < 5; i++) { |
| theta += rotation; |
| starPath.lineTo( |
| starCenter.dx + radius * math.cos(theta), |
| starCenter.dy + radius * math.sin(theta) |
| ); |
| } |
| canvas.drawPath( |
| starPath, |
| ui.Paint() |
| ..color = const ui.Color(0xFFFF00FF) |
| ..style = ui.PaintingStyle.fill |
| ); |
| canvas.restore(); |
| |
| // Draw the Squiggle |
| canvas.save(); |
| canvas.clipRect(kGreenSquiggleRegion); |
| final ui.Path squigglePath = ui.Path(); |
| squigglePath.moveTo(kGreenSquiggleRegion.topCenter.dx, kGreenSquiggleRegion.topCenter.dy + 2.0); |
| squigglePath.cubicTo( |
| kGreenSquiggleRegion.left - 10.0, kGreenSquiggleRegion.top + kGreenSquiggleRegion.height * 0.33, |
| kGreenSquiggleRegion.right + 10.0, kGreenSquiggleRegion.top + kGreenSquiggleRegion.height * 0.66, |
| kGreenSquiggleRegion.bottomCenter.dx, kGreenSquiggleRegion.bottomCenter.dy - 2.0 |
| ); |
| canvas.drawPath( |
| squigglePath, |
| ui.Paint() |
| ..color = const ui.Color(0xFF00FF00) |
| ..style = ui.PaintingStyle.stroke |
| ..strokeWidth = 5.0 |
| ); |
| canvas.restore(); |
| |
| final ui.Picture picture = recorder.endRecording(); |
| return picture.toImageSync( |
| kTotalAtlasRegion.width.toInt(), |
| kTotalAtlasRegion.height.toInt() |
| ); |
| } |
| |
| Future<void> testMain() async { |
| setUpUnitTests( |
| setUpTestViewDimensions: false, |
| ); |
| |
| const ui.Rect region = ui.Rect.fromLTWH(0, 0, 300, 300); |
| |
| test('render atlas', () async { |
| final ui.PictureRecorder recorder = ui.PictureRecorder(); |
| final ui.Canvas canvas = ui.Canvas(recorder, region); |
| final ui.Image atlas = generateAtlas(); |
| canvas.drawImage(atlas, ui.Offset.zero, ui.Paint()); |
| await drawPictureUsingCurrentRenderer(recorder.endRecording()); |
| await matchGoldenFile('ui_atlas.png', region: region); |
| }, skip: isHtml); // HTML renderer doesn't support drawAtlas |
| |
| test('drawAtlas', () async { |
| final ui.PictureRecorder recorder = ui.PictureRecorder(); |
| final ui.Canvas canvas = ui.Canvas(recorder, region); |
| final ui.Image atlas = generateAtlas(); |
| final List<ui.RSTransform> transforms = List<ui.RSTransform>.generate( |
| 12, (int index) { |
| const double radius = 100; |
| const double rotation = math.pi / 6.0; |
| final double angle = rotation * index; |
| final double scos = math.sin(angle); |
| final double ssin = math.cos(angle); |
| return ui.RSTransform( |
| scos, |
| ssin, |
| region.center.dx + radius * scos, |
| region.center.dy + radius * ssin, |
| ); |
| } |
| ); |
| final List<ui.Rect> rects = <ui.Rect>[ |
| kBlueSquareRegion, |
| kRedCircleRegion, |
| kMagentaStarRegion, |
| kGreenSquiggleRegion, |
| kBlueSquareRegion, |
| kRedCircleRegion, |
| kMagentaStarRegion, |
| kGreenSquiggleRegion, |
| kBlueSquareRegion, |
| kRedCircleRegion, |
| kMagentaStarRegion, |
| kGreenSquiggleRegion, |
| ]; |
| canvas.drawAtlas( |
| atlas, transforms, rects, null, null, null, ui.Paint()); |
| |
| await drawPictureUsingCurrentRenderer(recorder.endRecording()); |
| await matchGoldenFile('ui_draw_atlas.png', region: region); |
| }, skip: isHtml); // HTML renderer doesn't support drawAtlas |
| |
| test('drawAtlasRaw', () async { |
| final ui.PictureRecorder recorder = ui.PictureRecorder(); |
| final ui.Canvas canvas = ui.Canvas(recorder, region); |
| final ui.Image atlas = generateAtlas(); |
| final Float32List transforms = Float32List(12 * 4); |
| for (int i = 0; i < 12; i++) { |
| const double radius = 100; |
| const double rotation = math.pi / 6.0; |
| final double angle = rotation * i; |
| final double scos = math.sin(angle); |
| final double ssin = math.cos(angle); |
| transforms[i * 4] = scos; |
| transforms[i * 4 + 1] = ssin; |
| transforms[i * 4 + 2] = region.center.dx + radius * scos; |
| transforms[i * 4 + 3] = region.center.dy + radius * ssin; |
| } |
| final List<ui.Rect> rects = <ui.Rect>[ |
| kBlueSquareRegion, |
| kRedCircleRegion, |
| kMagentaStarRegion, |
| kGreenSquiggleRegion, |
| kBlueSquareRegion, |
| kRedCircleRegion, |
| kMagentaStarRegion, |
| kGreenSquiggleRegion, |
| kBlueSquareRegion, |
| kRedCircleRegion, |
| kMagentaStarRegion, |
| kGreenSquiggleRegion, |
| ]; |
| final Float32List rawRects = Float32List(rects.length * 4); |
| for (int i = 0; i < rects.length; i++) { |
| rawRects[i * 4] = rects[i].left; |
| rawRects[i * 4 + 1] = rects[i].top; |
| rawRects[i * 4 + 2] = rects[i].right; |
| rawRects[i * 4 + 3] = rects[i].bottom; |
| } |
| |
| final Int32List colors = Int32List(12); |
| for (int i = 0; i < 12; i++) { |
| final int rgb = 0xFF << (8 * (i % 3)); |
| colors[i] = 0xFF000000 | rgb; |
| } |
| canvas.drawRawAtlas( |
| atlas, |
| transforms, |
| rawRects, |
| colors, |
| ui.BlendMode.dstIn, |
| null, |
| ui.Paint() |
| ); |
| |
| await drawPictureUsingCurrentRenderer(recorder.endRecording()); |
| await matchGoldenFile('ui_draw_atlas_raw.png', region: region); |
| }, skip: isHtml); // HTML renderer doesn't support drawAtlas |
| } |