forked from flutter/flutter
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[web] Fixes incorrect transform when context save and transforms are …
…deferred. (flutter#16412) * Fix transform order in clipStack replay
- Loading branch information
Showing
3 changed files
with
146 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
repository: https://github.com/flutter/goldens.git | ||
revision: 43254f4abddc2542ece540f222545970caf12908 | ||
revision: 1637835646ef187884ceeb59011d70c463429876 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
100 changes: 100 additions & 0 deletions
100
lib/web_ui/test/golden_tests/engine/canvas_context_test.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
// 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:js_util' as js_util; | ||
|
||
import 'package:ui/ui.dart' hide TextStyle; | ||
import 'package:ui/src/engine.dart' as engine; | ||
import 'package:test/test.dart'; | ||
|
||
import 'package:web_engine_tester/golden_tester.dart'; | ||
|
||
/// Tests context save/restore. | ||
void main() 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(engine.RecordingCanvas rc, String fileName, | ||
{Rect region = const Rect.fromLTWH(0, 0, 500, 500)}) async { | ||
final engine.EngineCanvas engineCanvas = engine.BitmapCanvas(screenRect); | ||
|
||
rc.apply(engineCanvas); | ||
|
||
// 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, maxDiffRate: 0.1); | ||
} 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(); | ||
}); | ||
|
||
// Regression test for https://github.com/flutter/flutter/issues/49429 | ||
// Should clip with correct transform. | ||
test('Clips image with oval clip path', () async { | ||
final engine.RecordingCanvas rc = | ||
engine.RecordingCanvas(const Rect.fromLTRB(0, 0, 400, 300)); | ||
final Paint paint = Paint() | ||
..color = Color(0xFF00FF00) | ||
..style = PaintingStyle.fill; | ||
rc.save(); | ||
final Path ovalPath = Path(); | ||
ovalPath.addOval(Rect.fromLTWH(100, 30, 200, 100)); | ||
rc.clipPath(ovalPath); | ||
rc.translate(-500, -500); | ||
rc.save(); | ||
rc.translate(500, 500); | ||
rc.drawPath(ovalPath, paint); | ||
// The line below was causing SaveClipStack to incorrectly set | ||
// transform before path painting. | ||
rc.translate(-1000, -1000); | ||
rc.save(); | ||
rc.restore(); | ||
rc.restore(); | ||
rc.restore(); | ||
// The rectangle should paint without clipping since we restored | ||
// context. | ||
rc.drawRect(Rect.fromLTWH(0, 0, 4, 200), paint); | ||
await _checkScreenshot(rc, 'context_save_restore_transform'); | ||
}); | ||
|
||
test('Should restore clip path', () async { | ||
final engine.RecordingCanvas rc = | ||
engine.RecordingCanvas(const Rect.fromLTRB(0, 0, 400, 300)); | ||
final Paint goodPaint = Paint() | ||
..color = Color(0x8000FF00) | ||
..style = PaintingStyle.fill; | ||
final Paint badPaint = Paint() | ||
..color = Color(0xFFFF0000) | ||
..style = PaintingStyle.fill; | ||
rc.save(); | ||
final Path ovalPath = Path(); | ||
ovalPath.addOval(Rect.fromLTWH(100, 30, 200, 100)); | ||
rc.clipPath(ovalPath); | ||
rc.translate(-500, -500); | ||
rc.save(); | ||
rc.restore(); | ||
// The rectangle should be clipped against oval. | ||
rc.drawRect(Rect.fromLTWH(0, 0, 300, 300), badPaint); | ||
rc.restore(); | ||
// The rectangle should paint without clipping since we restored | ||
// context. | ||
rc.drawRect(Rect.fromLTWH(0, 0, 200, 200), goodPaint); | ||
await _checkScreenshot(rc, 'context_save_restore_clip'); | ||
}); | ||
} |