Revert onrender change (flutter/engine#49333)

This reverts https://github.com/flutter/engine/pull/49214 and
https://github.com/flutter/engine/pull/48758.

https://github.com/flutter/engine/pull/49214 appears to cause a Flutter
Gold diff during the engine roll. See
https://github.com/flutter/flutter/pull/140434 for an example. It's
unclear to me whether this is an expected diff and should be approved or
unexpected and should be reverting, so reverting to the last previous
rollable state.

## Pre-launch Checklist

- [ ] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [ ] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [ ] I read and followed the [Flutter Style Guide] and the [C++,
Objective-C, Java style guides].
- [ ] I listed at least one issue that this PR fixes in the description
above.
- [ ] I added new tests to check the change I am making or feature I am
adding, or the PR is [test-exempt]. See [testing the engine] for
instructions on writing and running engine tests.
- [ ] I updated/added relevant documentation (doc comments with `///`).
- [ ] I signed the [CLA].
- [ ] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#overview
[Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene
[test-exempt]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo
[C++, Objective-C, Java style guides]:
https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
[testing the engine]:
https://github.com/flutter/flutter/wiki/Testing-the-engine
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes
[Discord]: https://github.com/flutter/flutter/wiki/Chat
This commit is contained in:
Chris Bracken 2023-12-21 11:00:30 -08:00 committed by GitHub
parent 409fb68d25
commit 535bb52c87
31 changed files with 210 additions and 294 deletions

View File

@ -80,7 +80,7 @@ abstract class PlatformDispatcher {
void scheduleFrame();
Future<void> render(Scene scene, [FlutterView view]);
void render(Scene scene, [FlutterView view]);
AccessibilityFeatures get accessibilityFeatures;

View File

@ -364,7 +364,7 @@ class HtmlViewEmbedder {
sceneHost.append(_svgPathDefs!);
}
Future<void> submitFrame() async {
void submitFrame() {
final ViewListDiffResult? diffResult =
(_activeCompositionOrder.isEmpty || _compositionOrder.isEmpty)
? null
@ -388,7 +388,7 @@ class HtmlViewEmbedder {
_context.pictureRecorders[pictureRecorderIndex].endRecording());
pictureRecorderIndex++;
}
await rasterizer.rasterizeToCanvas(overlay, pictures);
rasterizer.rasterizeToCanvas(overlay, pictures);
}
for (final CkPictureRecorder recorder
in _context.pictureRecordersCreatedDuringPreroll) {
@ -443,7 +443,8 @@ class HtmlViewEmbedder {
sceneHost.insertBefore(platformViewRoot, elementToInsertBefore);
final RenderCanvas? overlay = _overlays[viewId];
if (overlay != null) {
sceneHost.insertBefore(overlay.htmlElement, elementToInsertBefore);
sceneHost.insertBefore(
overlay.htmlElement, elementToInsertBefore);
}
} else {
final DomElement platformViewRoot = _viewClipChains[viewId]!.root;
@ -653,8 +654,6 @@ class HtmlViewEmbedder {
}
}
_svgClipDefs.clear();
_svgPathDefs?.remove();
_svgPathDefs = null;
}
static void removeElement(DomElement element) {

View File

@ -30,7 +30,7 @@ class Rasterizer {
/// Creates a new frame from this rasterizer's surface, draws the given
/// [LayerTree] into it, and then submits the frame.
Future<void> draw(LayerTree layerTree) async {
void draw(LayerTree layerTree) {
final ui.Size frameSize = view.physicalSize;
if (frameSize.isEmpty) {
// Available drawing area is empty. Skip drawing.
@ -49,10 +49,10 @@ class Rasterizer {
compositorFrame.raster(layerTree, ignoreRasterCache: true);
sceneHost.prepend(renderCanvasFactory.baseCanvas.htmlElement);
await rasterizeToCanvas(renderCanvasFactory.baseCanvas,
rasterizeToCanvas(renderCanvasFactory.baseCanvas,
<CkPicture>[pictureRecorder.endRecording()]);
await viewEmbedder.submitFrame();
viewEmbedder.submitFrame();
}
/// Disposes of this rasterizer.

View File

@ -85,7 +85,6 @@ class CanvasKitRenderer implements Renderer {
viewManager.onViewDisposed.listen(_onViewDisposed);
_instance = this;
}();
registerHotRestartListener(dispose);
return _initialized;
}
@ -403,7 +402,7 @@ class CanvasKitRenderer implements Renderer {
CkParagraphBuilder(style);
@override
Future<void> renderScene(ui.Scene scene, ui.FlutterView view) async {
void renderScene(ui.Scene scene, ui.FlutterView view) {
// "Build finish" and "raster start" happen back-to-back because we
// render on the same thread, so there's no overhead from hopping to
// another thread.
@ -418,7 +417,7 @@ class CanvasKitRenderer implements Renderer {
"Unable to render to a view which hasn't been registered");
final Rasterizer rasterizer = _rasterizers[view.viewId]!;
await rasterizer.draw((scene as LayerScene).layerTree);
rasterizer.draw((scene as LayerScene).layerTree);
frameTimingsOnRasterFinish();
}
@ -452,7 +451,6 @@ class CanvasKitRenderer implements Renderer {
rasterizer.dispose();
}
_rasterizers.clear();
clearFragmentProgramCache();
}
@override

View File

@ -115,18 +115,22 @@ class Surface {
_surface!.flush();
if (browserSupportsCreateImageBitmap) {
JSObject bitmapSource;
DomImageBitmap bitmap;
if (Surface.offscreenCanvasSupported) {
bitmapSource = _offscreenCanvas! as JSObject;
bitmap = (await createImageBitmap(_offscreenCanvas! as JSObject, (
x: 0,
y: _pixelHeight - frameSize.height.toInt(),
width: frameSize.width.toInt(),
height: frameSize.height.toInt(),
)).toDart)! as DomImageBitmap;
} else {
bitmapSource = _canvasElement! as JSObject;
bitmap = (await createImageBitmap(_canvasElement! as JSObject, (
x: 0,
y: _pixelHeight - frameSize.height.toInt(),
width: frameSize.width.toInt(),
height: frameSize.height.toInt()
)).toDart)! as DomImageBitmap;
}
final DomImageBitmap bitmap = await createImageBitmap(bitmapSource, (
x: 0,
y: _pixelHeight - frameSize.height.toInt(),
width: frameSize.width.toInt(),
height: frameSize.height.toInt(),
));
canvas.render(bitmap);
} else {
// If the browser doesn't support `createImageBitmap` (e.g. Safari 14)

View File

@ -210,16 +210,14 @@ external JSPromise<JSAny?> _createImageBitmap2(
JSNumber width,
JSNumber height,
);
Future<DomImageBitmap> createImageBitmap(JSAny source,
JSPromise<JSAny?> createImageBitmap(JSAny source,
[({int x, int y, int width, int height})? bounds]) {
JSPromise<JSAny?> jsPromise;
if (bounds != null) {
jsPromise = _createImageBitmap2(source, bounds.x.toJS, bounds.y.toJS,
return _createImageBitmap2(source, bounds.x.toJS, bounds.y.toJS,
bounds.width.toJS, bounds.height.toJS);
} else {
jsPromise = _createImageBitmap1(source);
return _createImageBitmap1(source);
}
return js_util.promiseToFuture<DomImageBitmap>(jsPromise);
}
@JS()

View File

@ -31,7 +31,6 @@ class HtmlRenderer implements Renderer {
// to make the unpacking happen while we are waiting for network requests.
lineLookup;
});
registerHotRestartListener(clearFragmentProgramCache);
_instance = this;
}
@ -324,7 +323,7 @@ class HtmlRenderer implements Renderer {
CanvasParagraphBuilder(style as EngineParagraphStyle);
@override
Future<void> renderScene(ui.Scene scene, ui.FlutterView view) async {
void renderScene(ui.Scene scene, ui.FlutterView view) {
final EngineFlutterView implicitView = EnginePlatformDispatcher.instance.implicitView!;
implicitView.dom.setScene((scene as SurfaceScene).webOnlyRootElement!);
frameTimingsOnRasterFinish();

View File

@ -213,10 +213,6 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher {
}
}
/// A set of views which have rendered in the current `onBeginFrame` or
/// `onDrawFrame` scope.
Set<ui.FlutterView>? _viewsRenderedInCurrentFrame;
/// A callback invoked when any window begins a frame.
///
/// A callback that is invoked to notify the application that it is an
@ -239,9 +235,7 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher {
/// Engine code should use this method instead of the callback directly.
/// Otherwise zones won't work properly.
void invokeOnBeginFrame(Duration duration) {
_viewsRenderedInCurrentFrame = <ui.FlutterView>{};
invoke1<Duration>(_onBeginFrame, _onBeginFrameZone, duration);
_viewsRenderedInCurrentFrame = null;
}
/// A callback that is invoked for each frame after [onBeginFrame] has
@ -262,9 +256,7 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher {
/// Engine code should use this method instead of the callback directly.
/// Otherwise zones won't work properly.
void invokeOnDrawFrame() {
_viewsRenderedInCurrentFrame = <ui.FlutterView>{};
invoke(_onDrawFrame, _onDrawFrameZone);
_viewsRenderedInCurrentFrame = null;
}
/// A callback that is invoked when pointer data is available.
@ -761,23 +753,14 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher {
/// * [RendererBinding], the Flutter framework class which manages layout and
/// painting.
@override
Future<void> render(ui.Scene scene, [ui.FlutterView? view]) async {
void render(ui.Scene scene, [ui.FlutterView? view]) {
assert(view != null || implicitView != null,
'Calling render without a FlutterView');
if (view == null && implicitView == null) {
// If there is no view to render into, then this is a no-op.
return;
}
final ui.FlutterView viewToRender = view ?? implicitView!;
// Only render in an `onDrawFrame` or `onBeginFrame` scope. This is checked
// by checking if the `_viewsRenderedInCurrentFrame` is non-null and this
// view hasn't been rendered already in this scope.
final bool shouldRender =
_viewsRenderedInCurrentFrame?.add(viewToRender) ?? false;
if (shouldRender) {
await renderer.renderScene(scene, viewToRender);
}
renderer.renderScene(scene, view ?? implicitView!);
}
/// Additional accessibility features that may be enabled by the platform.
@ -1292,8 +1275,7 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher {
String get defaultRouteName {
// TODO(mdebbar): What should we do in multi-view mode?
// https://github.com/flutter/flutter/issues/139174
return _defaultRouteName ??=
implicitView?.browserHistory.currentPath ?? '/';
return _defaultRouteName ??= implicitView?.browserHistory.currentPath ?? '/';
}
/// Lazily initialized when the `defaultRouteName` getter is invoked.

View File

@ -222,5 +222,5 @@ abstract class Renderer {
ui.ParagraphBuilder createParagraphBuilder(ui.ParagraphStyle style);
Future<void> renderScene(ui.Scene scene, ui.FlutterView view);
FutureOr<void> renderScene(ui.Scene scene, ui.FlutterView view);
}

View File

@ -349,7 +349,6 @@ class SkwasmRenderer implements Renderer {
FutureOr<void> initialize() {
surface = SkwasmSurface();
sceneView = EngineSceneView(SkwasmPictureRenderer(surface));
registerHotRestartListener(clearFragmentProgramCache);
}
@override

View File

@ -150,7 +150,7 @@ class SkwasmRenderer implements Renderer {
}
@override
Future<void> renderScene(ui.Scene scene, ui.FlutterView view) {
void renderScene(ui.Scene scene, ui.FlutterView view) {
throw UnimplementedError('Skwasm not implemented on this platform.');
}

View File

@ -9,7 +9,7 @@ import 'package:meta/meta.dart';
import 'package:ui/ui.dart' as ui;
import 'package:ui/ui_web/src/ui_web.dart' as ui_web;
import '../engine.dart' show DimensionsProvider, registerHotRestartListener;
import '../engine.dart' show DimensionsProvider, registerHotRestartListener, renderer;
import 'browser_detection.dart';
import 'display.dart';
import 'dom.dart';
@ -58,8 +58,7 @@ base class EngineFlutterView implements ui.FlutterView {
// by the public `EngineFlutterView` constructor).
DomElement? hostElement,
) : embeddingStrategy = EmbeddingStrategy.create(hostElement: hostElement),
dimensionsProvider =
DimensionsProvider.create(hostElement: hostElement) {
dimensionsProvider = DimensionsProvider.create(hostElement: hostElement) {
// The embeddingStrategy will take care of cleaning up the rootElement on
// hot restart.
embeddingStrategy.attachViewRoot(dom.rootElement);
@ -71,8 +70,7 @@ base class EngineFlutterView implements ui.FlutterView {
static EngineFlutterWindow implicit(
EnginePlatformDispatcher platformDispatcher,
DomElement? hostElement,
) =>
EngineFlutterWindow._(platformDispatcher, hostElement);
) => EngineFlutterWindow._(platformDispatcher, hostElement);
@override
final int viewId;
@ -102,6 +100,8 @@ base class EngineFlutterView implements ui.FlutterView {
dimensionsProvider.close();
pointerBinding.dispose();
dom.rootElement.remove();
// TODO(harryterkelsen): What should we do about this in multi-view?
renderer.clearFragmentProgramCache();
semantics.reset();
}
@ -114,8 +114,7 @@ base class EngineFlutterView implements ui.FlutterView {
@override
void updateSemantics(ui.SemanticsUpdate update) {
assert(!isDisposed,
'Trying to update semantics on a disposed EngineFlutterView.');
assert(!isDisposed, 'Trying to update semantics on a disposed EngineFlutterView.');
semantics.updateSemantics(update);
}
@ -128,18 +127,15 @@ base class EngineFlutterView implements ui.FlutterView {
late final ContextMenu contextMenu = ContextMenu(dom.rootElement);
late final DomManager dom =
DomManager(viewId: viewId, devicePixelRatio: devicePixelRatio);
late final DomManager dom = DomManager(viewId: viewId, devicePixelRatio: devicePixelRatio);
late final PointerBinding pointerBinding;
// TODO(goderbauer): Provide API to configure constraints. See also TODO in "render".
@override
ViewConstraints get physicalConstraints =>
ViewConstraints.tight(physicalSize);
ViewConstraints get physicalConstraints => ViewConstraints.tight(physicalSize);
late final EngineSemanticsOwner semantics =
EngineSemanticsOwner(dom.semanticsHost);
late final EngineSemanticsOwner semantics = EngineSemanticsOwner(dom.semanticsHost);
@override
ui.Size get physicalSize {
@ -188,8 +184,7 @@ base class EngineFlutterView implements ui.FlutterView {
ui.GestureSettings get gestureSettings => _viewConfiguration.gestureSettings;
@override
List<ui.DisplayFeature> get displayFeatures =>
_viewConfiguration.displayFeatures;
List<ui.DisplayFeature> get displayFeatures => _viewConfiguration.displayFeatures;
@override
EngineFlutterDisplay get display => EngineFlutterDisplay.instance;
@ -245,14 +240,11 @@ base class EngineFlutterView implements ui.FlutterView {
// Return false if the previous dimensions are not set.
if (_physicalSize != null) {
// First confirm both height and width are effected.
if (_physicalSize!.height != newPhysicalSize.height &&
_physicalSize!.width != newPhysicalSize.width) {
if (_physicalSize!.height != newPhysicalSize.height && _physicalSize!.width != newPhysicalSize.width) {
// If prior to rotation height is bigger than width it should be the
// opposite after the rotation and vice versa.
if ((_physicalSize!.height > _physicalSize!.width &&
newPhysicalSize.height < newPhysicalSize.width) ||
(_physicalSize!.width > _physicalSize!.height &&
newPhysicalSize.width < newPhysicalSize.height)) {
if ((_physicalSize!.height > _physicalSize!.width && newPhysicalSize.height < newPhysicalSize.width) ||
(_physicalSize!.width > _physicalSize!.height && newPhysicalSize.width < newPhysicalSize.height)) {
// Rotation detected
return true;
}
@ -277,8 +269,7 @@ final class _EngineFlutterViewImpl extends EngineFlutterView {
}
/// The Web implementation of [ui.SingletonFlutterWindow].
final class EngineFlutterWindow extends EngineFlutterView
implements ui.SingletonFlutterWindow {
final class EngineFlutterWindow extends EngineFlutterView implements ui.SingletonFlutterWindow {
EngineFlutterWindow._(
EnginePlatformDispatcher platformDispatcher,
DomElement? hostElement,
@ -325,8 +316,7 @@ final class EngineFlutterWindow extends EngineFlutterView
double get textScaleFactor => platformDispatcher.textScaleFactor;
@override
bool get nativeSpellCheckServiceDefined =>
platformDispatcher.nativeSpellCheckServiceDefined;
bool get nativeSpellCheckServiceDefined => platformDispatcher.nativeSpellCheckServiceDefined;
@override
bool get brieflyShowPassword => platformDispatcher.brieflyShowPassword;
@ -335,8 +325,7 @@ final class EngineFlutterWindow extends EngineFlutterView
bool get alwaysUse24HourFormat => platformDispatcher.alwaysUse24HourFormat;
@override
ui.VoidCallback? get onTextScaleFactorChanged =>
platformDispatcher.onTextScaleFactorChanged;
ui.VoidCallback? get onTextScaleFactorChanged => platformDispatcher.onTextScaleFactorChanged;
@override
set onTextScaleFactorChanged(ui.VoidCallback? callback) {
platformDispatcher.onTextScaleFactorChanged = callback;
@ -346,8 +335,7 @@ final class EngineFlutterWindow extends EngineFlutterView
ui.Brightness get platformBrightness => platformDispatcher.platformBrightness;
@override
ui.VoidCallback? get onPlatformBrightnessChanged =>
platformDispatcher.onPlatformBrightnessChanged;
ui.VoidCallback? get onPlatformBrightnessChanged => platformDispatcher.onPlatformBrightnessChanged;
@override
set onPlatformBrightnessChanged(ui.VoidCallback? callback) {
platformDispatcher.onPlatformBrightnessChanged = callback;
@ -357,8 +345,7 @@ final class EngineFlutterWindow extends EngineFlutterView
String? get systemFontFamily => platformDispatcher.systemFontFamily;
@override
ui.VoidCallback? get onSystemFontFamilyChanged =>
platformDispatcher.onSystemFontFamilyChanged;
ui.VoidCallback? get onSystemFontFamilyChanged => platformDispatcher.onSystemFontFamilyChanged;
@override
set onSystemFontFamilyChanged(ui.VoidCallback? callback) {
platformDispatcher.onSystemFontFamilyChanged = callback;
@ -386,8 +373,7 @@ final class EngineFlutterWindow extends EngineFlutterView
}
@override
ui.PointerDataPacketCallback? get onPointerDataPacket =>
platformDispatcher.onPointerDataPacket;
ui.PointerDataPacketCallback? get onPointerDataPacket => platformDispatcher.onPointerDataPacket;
@override
set onPointerDataPacket(ui.PointerDataPacketCallback? callback) {
platformDispatcher.onPointerDataPacket = callback;
@ -410,8 +396,7 @@ final class EngineFlutterWindow extends EngineFlutterView
bool get semanticsEnabled => platformDispatcher.semanticsEnabled;
@override
ui.VoidCallback? get onSemanticsEnabledChanged =>
platformDispatcher.onSemanticsEnabledChanged;
ui.VoidCallback? get onSemanticsEnabledChanged => platformDispatcher.onSemanticsEnabledChanged;
@override
set onSemanticsEnabledChanged(ui.VoidCallback? callback) {
platformDispatcher.onSemanticsEnabledChanged = callback;
@ -426,8 +411,7 @@ final class EngineFlutterWindow extends EngineFlutterView
set onFrameDataChanged(ui.VoidCallback? callback) {}
@override
ui.AccessibilityFeatures get accessibilityFeatures =>
platformDispatcher.accessibilityFeatures;
ui.AccessibilityFeatures get accessibilityFeatures => platformDispatcher.accessibilityFeatures;
@override
ui.VoidCallback? get onAccessibilityFeaturesChanged =>
@ -447,16 +431,14 @@ final class EngineFlutterWindow extends EngineFlutterView
}
@override
ui.PlatformMessageCallback? get onPlatformMessage =>
platformDispatcher.onPlatformMessage;
ui.PlatformMessageCallback? get onPlatformMessage => platformDispatcher.onPlatformMessage;
@override
set onPlatformMessage(ui.PlatformMessageCallback? callback) {
platformDispatcher.onPlatformMessage = callback;
}
@override
void setIsolateDebugName(String name) =>
ui.PlatformDispatcher.instance.setIsolateDebugName(name);
void setIsolateDebugName(String name) => ui.PlatformDispatcher.instance.setIsolateDebugName(name);
/// Handles the browser history integration to allow users to use the back
/// button, etc.
@ -562,8 +544,7 @@ final class EngineFlutterWindow extends EngineFlutterView
Future<bool> handleNavigationMessage(ByteData? data) async {
return _waitInTheLine(() async {
final MethodCall decoded = const JSONMethodCodec().decodeMethodCall(data);
final Map<String, dynamic>? arguments =
decoded.arguments as Map<String, dynamic>?;
final Map<String, dynamic>? arguments = decoded.arguments as Map<String, dynamic>?;
switch (decoded.method) {
case 'selectMultiEntryHistory':
await _useMultiEntryBrowserHistory();
@ -587,9 +568,7 @@ final class EngineFlutterWindow extends EngineFlutterView
path = Uri.decodeComponent(
Uri(
path: uri.path.isEmpty ? '/' : uri.path,
queryParameters: uri.queryParametersAll.isEmpty
? null
: uri.queryParametersAll,
queryParameters: uri.queryParametersAll.isEmpty ? null : uri.queryParametersAll,
fragment: uri.fragment.isEmpty ? null : uri.fragment,
).toString(),
);
@ -665,7 +644,6 @@ EngineFlutterWindow get window {
);
return _window!;
}
EngineFlutterWindow? _window;
/// Initializes the [window] (aka the implicit view), if it's not already
@ -711,10 +689,10 @@ class ViewConstraints implements ui.ViewConstraints {
});
ViewConstraints.tight(ui.Size size)
: minWidth = size.width,
maxWidth = size.width,
minHeight = size.height,
maxHeight = size.height;
: minWidth = size.width,
maxWidth = size.width,
minHeight = size.height,
maxHeight = size.height;
@override
final double minWidth;
@ -727,17 +705,15 @@ class ViewConstraints implements ui.ViewConstraints {
@override
bool isSatisfiedBy(ui.Size size) {
return (minWidth <= size.width) &&
(size.width <= maxWidth) &&
(minHeight <= size.height) &&
(size.height <= maxHeight);
return (minWidth <= size.width) && (size.width <= maxWidth) &&
(minHeight <= size.height) && (size.height <= maxHeight);
}
@override
bool get isTight => minWidth >= maxWidth && minHeight >= maxHeight;
@override
ViewConstraints operator /(double factor) {
ViewConstraints operator/(double factor) {
return ViewConstraints(
minWidth: minWidth / factor,
maxWidth: maxWidth / factor,
@ -754,11 +730,11 @@ class ViewConstraints implements ui.ViewConstraints {
if (other.runtimeType != runtimeType) {
return false;
}
return other is ViewConstraints &&
other.minWidth == minWidth &&
other.maxWidth == maxWidth &&
other.minHeight == minHeight &&
other.maxHeight == maxHeight;
return other is ViewConstraints
&& other.minWidth == minWidth
&& other.maxWidth == maxWidth
&& other.minHeight == minHeight
&& other.maxHeight == maxHeight;
}
@override
@ -769,10 +745,8 @@ class ViewConstraints implements ui.ViewConstraints {
if (minWidth == double.infinity && minHeight == double.infinity) {
return 'ViewConstraints(biggest)';
}
if (minWidth == 0 &&
maxWidth == double.infinity &&
minHeight == 0 &&
maxHeight == double.infinity) {
if (minWidth == 0 && maxWidth == double.infinity &&
minHeight == 0 && maxHeight == double.infinity) {
return 'ViewConstraints(unconstrained)';
}
String describe(double min, double max, String dim) {
@ -781,7 +755,6 @@ class ViewConstraints implements ui.ViewConstraints {
}
return '${min.toStringAsFixed(1)}<=$dim<=${max.toStringAsFixed(1)}';
}
final String width = describe(minWidth, maxWidth, 'w');
final String height = describe(minHeight, maxHeight, 'h');
return 'ViewConstraints($width, $height)';

View File

@ -7,6 +7,8 @@ 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.dart';
void main() {
@ -47,8 +49,8 @@ void testMain() {
builder.pushOffset(0, 0);
builder.addPicture(ui.Offset.zero, checkerboard);
builder.pushBackdropFilter(ui.ImageFilter.blur(sigmaX: 10, sigmaY: 10));
await matchSceneGolden(
'canvaskit_backdropfilter_blur_edges.png', builder.build(),
CanvasKitRenderer.instance.renderScene(builder.build(), implicitView);
await matchGoldenFile('canvaskit_backdropfilter_blur_edges.png',
region: region);
});
test('ImageFilter with ColorFilter as child', () async {
@ -60,7 +62,9 @@ void testMain() {
final CkPictureRecorder recorder = CkPictureRecorder();
final CkCanvas canvas = recorder.beginRecording(region);
final ui.ColorFilter colorFilter = ui.ColorFilter.mode(
const ui.Color(0XFF00FF00).withOpacity(0.55), ui.BlendMode.darken);
const ui.Color(0XFF00FF00).withOpacity(0.55),
ui.BlendMode.darken
);
// using a colorFilter as an imageFilter for backDrop filter
builder.pushBackdropFilter(colorFilter);
@ -71,10 +75,7 @@ void testMain() {
);
final CkPicture redCircle1 = recorder.endRecording();
builder.addPicture(ui.Offset.zero, redCircle1);
await matchSceneGolden(
'canvaskit_red_circle_green_backdrop_colorFilter.png',
builder.build(),
region: region);
await matchSceneGolden('canvaskit_red_circle_green_backdrop_colorFilter.png', builder.build(), region: region);
});
// TODO(hterkelsen): https://github.com/flutter/flutter/issues/71520
}, skip: isSafari || isFirefox);

View File

@ -11,6 +11,8 @@ import 'package:ui/src/engine.dart';
import 'package:ui/ui.dart' as ui;
import 'package:ui/ui_web/src/ui_web.dart' as ui_web;
import 'package:web_engine_tester/golden_tester.dart';
import 'common.dart';
void main() {
@ -145,14 +147,16 @@ void testMain() {
builder.pushOffset(0, 0);
builder.addPicture(ui.Offset.zero, picture);
final LayerScene scene = builder.build();
await renderScene(scene);
CanvasKitRenderer.instance.renderScene(scene, implicitView);
// Now draw an empty layer tree and confirm that the red rectangle is
// no longer drawn.
final LayerSceneBuilder emptySceneBuilder = LayerSceneBuilder();
emptySceneBuilder.pushOffset(0, 0);
final LayerScene emptyScene = emptySceneBuilder.build();
await matchSceneGolden('canvaskit_empty_scene.png', emptyScene,
CanvasKitRenderer.instance.renderScene(emptyScene, implicitView);
await matchGoldenFile('canvaskit_empty_scene.png',
region: const ui.Rect.fromLTRB(0, 0, 100, 100));
});
@ -207,8 +211,9 @@ void testMain() {
sb.pop();
// The below line should not throw an error.
await matchSceneGolden('cross_overlay_resources.png', sb.build(),
region: const ui.Rect.fromLTRB(0, 0, 100, 100));
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
await matchGoldenFile('cross_overlay_resources.png', region: const ui.Rect.fromLTRB(0, 0, 100, 100));
});
});
}

View File

@ -11,11 +11,8 @@ 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';
export '../common/rendering.dart' show renderScene;
const MethodCodec codec = StandardMethodCodec();
/// Common test setup for all CanvasKit unit-tests.
@ -47,10 +44,13 @@ CkPicture paintPicture(
Future<void> matchSceneGolden(
String goldenFile,
ui.Scene scene, {
LayerScene scene, {
required ui.Rect region,
}) async {
await renderScene(scene);
// TODO(harryterkelsen): Enforce the render rule. Render can only be called in
// the scope of `onBeginFrame` or `onDrawFrame`,
// https://github.com/flutter/flutter/issues/137073.
CanvasKitRenderer.instance.renderScene(scene, implicitView);
await matchGoldenFile(goldenFile, region: region);
}
@ -63,7 +63,7 @@ Future<void> matchPictureGolden(String goldenFile, CkPicture picture,
final LayerSceneBuilder sb = LayerSceneBuilder();
sb.pushOffset(0, 0);
sb.addPicture(ui.Offset.zero, picture);
await renderScene(sb.build());
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
await matchGoldenFile(goldenFile, region: region);
}

View File

@ -41,7 +41,7 @@ void testMain() {
final LayerSceneBuilder sb = LayerSceneBuilder();
sb.pushOffset(0, 0);
sb.addPlatformView(0, width: 10, height: 10);
await renderScene(sb.build());
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
// The platform view is now split in two parts. The contents live
// as a child of the glassPane, and the slot lives in the glassPane
@ -77,7 +77,7 @@ void testMain() {
sb.pushClipRRect(
ui.RRect.fromLTRBR(0, 0, 10, 10, const ui.Radius.circular(3)));
sb.addPlatformView(0, width: 10, height: 10);
await renderScene(sb.build());
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
expect(
sceneHost.querySelectorAll('#sk_path_defs').single,
@ -122,7 +122,7 @@ void testMain() {
sb.pushTransform(scaleMatrix.toFloat64());
sb.pushOffset(3, 3);
sb.addPlatformView(0, width: 10, height: 10);
await renderScene(sb.build());
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
// Transformations happen on the slot element.
final DomElement slotHost =
@ -148,7 +148,7 @@ void testMain() {
final LayerSceneBuilder sb = LayerSceneBuilder();
sb.addPlatformView(0, offset: const ui.Offset(3, 4), width: 5, height: 6);
await renderScene(sb.build());
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
final DomElement slotHost =
sceneHost.querySelector('flt-platform-view-slot')!;
@ -194,7 +194,7 @@ void testMain() {
sb.pushOffset(6, 6);
sb.addPlatformView(0, width: 10, height: 10);
sb.pop();
await renderScene(sb.build());
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
// Transformations happen on the slot element.
DomElement slotHost = sceneHost.querySelector('flt-platform-view-slot')!;
@ -214,7 +214,7 @@ void testMain() {
sb.pushClipRect(ui.Rect.largest);
sb.pushOffset(9, 9);
sb.addPlatformView(0, width: 10, height: 10);
await renderScene(sb.build());
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
// Transformations happen on the slot element.
slotHost = sceneHost.querySelector('flt-platform-view-slot')!;
@ -244,7 +244,7 @@ void testMain() {
sb.pushOffset(2, 2);
sb.pushOffset(3, 3);
sb.addPlatformView(0, width: 10, height: 10);
await renderScene(sb.build());
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
// Transformations happen on the slot element.
final DomElement slotHost =
@ -273,7 +273,7 @@ void testMain() {
sb.pushClipRect(ui.Rect.largest);
sb.pushOffset(9, 9);
sb.addPlatformView(0, width: 10, height: 10);
await renderScene(sb.build());
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
// Transformations happen on the slot element.
final DomElement slotHost =
@ -308,20 +308,20 @@ void testMain() {
platformViewIds.add(i);
}
Future<void> renderTestScene({required int viewCount}) async {
void renderTestScene({required int viewCount}) {
final LayerSceneBuilder sb = LayerSceneBuilder();
sb.pushOffset(0, 0);
for (int i = 0; i < viewCount; i++) {
sb.addPicture(ui.Offset.zero, testPicture);
sb.addPlatformView(i, width: 10, height: 10);
}
await renderScene(sb.build());
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
}
// Frame 1:
// Render: up to cache size platform views.
// Expect: main canvas plus platform view overlays.
await renderTestScene(viewCount: 8);
renderTestScene(viewCount: 8);
_expectSceneMatches(<_EmbeddedViewMarker>[
_overlay,
_platformView,
@ -344,13 +344,15 @@ void testMain() {
// Frame 2:
// Render: zero platform views.
// Expect: main canvas, no overlays.
await renderTestScene(viewCount: 0);
await Future<void>.delayed(Duration.zero);
renderTestScene(viewCount: 0);
_expectSceneMatches(<_EmbeddedViewMarker>[_overlay]);
// Frame 3:
// Render: less than cache size platform views.
// Expect: overlays reused.
await renderTestScene(viewCount: 6);
await Future<void>.delayed(Duration.zero);
renderTestScene(viewCount: 6);
_expectSceneMatches(<_EmbeddedViewMarker>[
_overlay,
_platformView,
@ -370,7 +372,8 @@ void testMain() {
// Frame 4:
// Render: more platform views than max overlay count.
// Expect: main canvas, backup overlay, maximum overlays.
await renderTestScene(viewCount: 16);
await Future<void>.delayed(Duration.zero);
renderTestScene(viewCount: 16);
_expectSceneMatches(<_EmbeddedViewMarker>[
_overlay,
_platformView,
@ -401,7 +404,8 @@ void testMain() {
// Frame 5:
// Render: zero platform views.
// Expect: main canvas, no overlays.
await renderTestScene(viewCount: 0);
await Future<void>.delayed(Duration.zero);
renderTestScene(viewCount: 0);
_expectSceneMatches(<_EmbeddedViewMarker>[_overlay]);
// Frame 6:
@ -422,7 +426,7 @@ void testMain() {
}
try {
await renderTestScene(viewCount: platformViewIds.length);
renderTestScene(viewCount: platformViewIds.length);
fail('Expected to throw');
} on AssertionError catch (error) {
expect(
@ -435,7 +439,7 @@ void testMain() {
// Render: a platform view after error.
// Expect: success. Just checking the system is not left in a corrupted state.
await createPlatformView(0, 'test-platform-view');
await renderTestScene(viewCount: 0);
renderTestScene(viewCount: 0);
_expectSceneMatches(<_EmbeddedViewMarker>[_overlay]);
for (int i = 0; i < 16; i++) {
@ -460,20 +464,20 @@ void testMain() {
platformViewIds.add(i);
}
Future<void> renderTestScene(List<int> views) async {
void renderTestScene(List<int> views) {
final LayerSceneBuilder sb = LayerSceneBuilder();
sb.pushOffset(0, 0);
for (final int view in views) {
sb.addPicture(ui.Offset.zero, testPicture);
sb.addPlatformView(view, width: 10, height: 10);
}
await renderScene(sb.build());
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
}
// Frame 1:
// Render: Views 1-10
// Expect: main canvas plus platform view overlays; empty cache.
await renderTestScene(<int>[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
renderTestScene(<int>[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
_expectSceneMatches(<_EmbeddedViewMarker>[
_overlay,
_platformView,
@ -498,7 +502,8 @@ void testMain() {
// Frame 2:
// Render: Views 2-11
// Expect: main canvas plus platform view overlays; empty cache.
await renderTestScene(<int>[2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
await Future<void>.delayed(Duration.zero);
renderTestScene(<int>[2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
_expectSceneMatches(<_EmbeddedViewMarker>[
_overlay,
_platformView,
@ -523,7 +528,8 @@ void testMain() {
// Frame 3:
// Render: Views 3-12
// Expect: main canvas plus platform view overlays; empty cache.
await renderTestScene(<int>[3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
await Future<void>.delayed(Duration.zero);
renderTestScene(<int>[3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
_expectSceneMatches(<_EmbeddedViewMarker>[
_overlay,
_platformView,
@ -548,7 +554,8 @@ void testMain() {
// Frame 4:
// Render: Views 3-12 again (same as last frame)
// Expect: main canvas plus platform view overlays; empty cache.
await renderTestScene(<int>[3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
await Future<void>.delayed(Duration.zero);
renderTestScene(<int>[3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
_expectSceneMatches(<_EmbeddedViewMarker>[
_overlay,
_platformView,
@ -573,6 +580,7 @@ void testMain() {
for (int i = 0; i < 20; i++) {
await disposePlatformView(i);
}
});
test('embeds and disposes of a platform view', () async {
@ -585,7 +593,7 @@ void testMain() {
LayerSceneBuilder sb = LayerSceneBuilder();
sb.pushOffset(0, 0);
sb.addPlatformView(0, width: 10, height: 10);
await renderScene(sb.build());
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
_expectSceneMatches(<_EmbeddedViewMarker>[
_overlay,
_platformView,
@ -598,7 +606,7 @@ void testMain() {
sb = LayerSceneBuilder();
sb.pushOffset(0, 0);
await renderScene(sb.build());
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
_expectSceneMatches(<_EmbeddedViewMarker>[
_overlay,
@ -634,7 +642,7 @@ void testMain() {
implicitView.debugPhysicalSizeOverride = const ui.Size(100, 100);
implicitView.debugForceResize();
await renderScene(sb.build());
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
_expectSceneMatches(<_EmbeddedViewMarker>[
_overlay,
_platformView,
@ -643,7 +651,7 @@ void testMain() {
implicitView.debugPhysicalSizeOverride = const ui.Size(200, 200);
implicitView.debugForceResize();
await renderScene(sb.build());
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
_expectSceneMatches(<_EmbeddedViewMarker>[
_overlay,
_platformView,
@ -667,7 +675,7 @@ void testMain() {
LayerSceneBuilder sb = LayerSceneBuilder();
sb.pushOffset(0, 0);
sb.addPlatformView(0, width: 10, height: 10);
await renderScene(sb.build());
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
_expectSceneMatches(<_EmbeddedViewMarker>[
_overlay,
_platformView,
@ -681,7 +689,7 @@ void testMain() {
sb = LayerSceneBuilder();
sb.pushOffset(0, 0);
sb.addPlatformView(1, width: 10, height: 10);
await renderScene(sb.build());
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
_expectSceneMatches(<_EmbeddedViewMarker>[
_overlay,
_platformView,
@ -697,7 +705,7 @@ void testMain() {
// the platform view.
sb = LayerSceneBuilder();
sb.pushOffset(0, 0);
await renderScene(sb.build());
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
_expectSceneMatches(<_EmbeddedViewMarker>[
_overlay,
]);
@ -722,29 +730,28 @@ void testMain() {
);
await createPlatformView(0, 'test-platform-view');
Future<void> renderTestScene() async {
void renderTestScene() {
final LayerSceneBuilder sb = LayerSceneBuilder();
sb.pushOffset(0, 0);
sb.pushClipRRect(
ui.RRect.fromLTRBR(0, 0, 10, 10, const ui.Radius.circular(3)));
sb.addPlatformView(0, width: 10, height: 10);
await renderScene(sb.build());
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
}
await renderTestScene();
final DomNode skPathDefs = sceneHost.querySelector('#sk_path_defs')!;
final DomElement? skPathDefs = sceneHost.querySelector('#sk_path_defs');
expect(
skPathDefs,
isNotNull,
reason: 'Should have created SVG paths after rendering the scene',
);
expect(skPathDefs!.childNodes, hasLength(1));
expect(skPathDefs.childNodes, hasLength(0));
await renderTestScene();
renderTestScene();
expect(skPathDefs.childNodes, hasLength(1));
await renderTestScene();
await Future<void>.delayed(Duration.zero);
renderTestScene();
expect(skPathDefs.childNodes, hasLength(1));
await Future<void>.delayed(Duration.zero);
renderTestScene();
expect(skPathDefs.childNodes, hasLength(1));
await disposePlatformView(0);
@ -764,7 +771,7 @@ void testMain() {
sb.addPlatformView(0, width: 10, height: 10);
sb.pop();
// The below line should not throw an error.
await renderScene(sb.build());
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
_expectSceneMatches(<_EmbeddedViewMarker>[
_overlay,
]);
@ -798,7 +805,7 @@ void testMain() {
sb.pushOffset(0, 0);
sb.addPlatformView(1, width: 10, height: 10);
sb.pop();
await renderScene(sb.build());
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
_expectSceneMatches(<_EmbeddedViewMarker>[
_overlay,
_platformView,
@ -809,7 +816,7 @@ void testMain() {
sb.addPlatformView(0, width: 10, height: 10);
sb.addPlatformView(1, width: 10, height: 10);
sb.pop();
await renderScene(sb.build());
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
_expectSceneMatches(<_EmbeddedViewMarker>[
_overlay,
_platformView,
@ -823,7 +830,7 @@ void testMain() {
sb.addPlatformView(1, width: 10, height: 10);
sb.addPlatformView(2, width: 10, height: 10);
sb.pop();
await renderScene(sb.build());
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
_expectSceneMatches(<_EmbeddedViewMarker>[
_overlay,
_platformView,
@ -842,7 +849,7 @@ void testMain() {
sb.addPlatformView(2, width: 10, height: 10);
sb.addPlatformView(3, width: 10, height: 10);
sb.pop();
await renderScene(sb.build());
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
_expectSceneMatches(<_EmbeddedViewMarker>[
_overlay,
_platformView,
@ -861,7 +868,7 @@ void testMain() {
sb.addPlatformView(3, width: 10, height: 10);
sb.addPlatformView(4, width: 10, height: 10);
sb.pop();
await renderScene(sb.build());
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
_expectSceneMatches(<_EmbeddedViewMarker>[
_overlay,
_platformView,
@ -882,7 +889,7 @@ void testMain() {
sb.addPlatformView(4, width: 10, height: 10);
sb.addPlatformView(5, width: 10, height: 10);
sb.pop();
await renderScene(sb.build());
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
_expectSceneMatches(<_EmbeddedViewMarker>[
_overlay,
_platformView,
@ -905,7 +912,7 @@ void testMain() {
sb.addPlatformView(5, width: 10, height: 10);
sb.addPlatformView(6, width: 10, height: 10);
sb.pop();
await renderScene(sb.build());
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
_expectSceneMatches(<_EmbeddedViewMarker>[
_overlay,
_platformView,
@ -927,7 +934,7 @@ void testMain() {
sb.addPlatformView(5, width: 10, height: 10);
sb.addPlatformView(6, width: 10, height: 10);
sb.pop();
await renderScene(sb.build());
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
_expectSceneMatches(<_EmbeddedViewMarker>[
_overlay,
_platformView,
@ -946,7 +953,7 @@ void testMain() {
sb.addPlatformView(3, width: 10, height: 10);
sb.addPlatformView(4, width: 10, height: 10);
sb.pop();
await renderScene(sb.build());
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
_expectSceneMatches(<_EmbeddedViewMarker>[
_overlay,
_platformView,
@ -963,7 +970,7 @@ void testMain() {
sb.addPlatformView(2, width: 10, height: 10);
sb.addPlatformView(1, width: 10, height: 10);
sb.pop();
await renderScene(sb.build());
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
_expectSceneMatches(<_EmbeddedViewMarker>[
_overlay,
_platformView,

View File

@ -10,6 +10,7 @@ import 'package:test/test.dart';
import 'package:ui/src/engine.dart';
import 'package:ui/ui.dart' as ui;
import 'package:ui/ui_web/src/ui_web.dart' as ui_web;
import 'package:web_engine_tester/golden_tester.dart';
import '../common/matchers.dart';
import 'common.dart';
@ -636,9 +637,11 @@ void _testForImageCodecs({required bool useBrowserImageDecoder}) {
canvas.drawImage(snapshot, ui.Offset.zero, CkPaint());
sb.addPicture(ui.Offset.zero, recorder.endRecording());
await matchSceneGolden(
'canvaskit_read_back_decoded_image_$mode.png', sb.build(),
region: const ui.Rect.fromLTRB(0, 0, 150, 150));
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
await matchGoldenFile(
'canvaskit_read_back_decoded_image_$mode.png',
region: const ui.Rect.fromLTRB(0, 0, 150, 150),
);
}
image.dispose();
@ -684,10 +687,11 @@ void _testForImageCodecs({required bool useBrowserImageDecoder}) {
canvas.drawParagraph(makeSimpleText('2'), const ui.Offset(2, 2));
sb.addPicture(ui.Offset.zero, recorder.endRecording());
}
await matchSceneGolden(
'canvaskit_cross_gl_context_image_$mode.png', sb.build(),
region: const ui.Rect.fromLTRB(0, 0, 100, 100));
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
await matchGoldenFile(
'canvaskit_cross_gl_context_image_$mode.png',
region: const ui.Rect.fromLTRB(0, 0, 100, 100),
);
await disposePlatformView(0);
});
@ -727,10 +731,11 @@ void _testForImageCodecs({required bool useBrowserImageDecoder}) {
canvas.restore();
sb.addPicture(ui.Offset.zero, recorder.endRecording());
}
await matchSceneGolden(
'canvaskit_picture_texture_toimage.png', sb.build(),
region: const ui.Rect.fromLTRB(0, 0, 128, 128));
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
await matchGoldenFile(
'canvaskit_picture_texture_toimage.png',
region: const ui.Rect.fromLTRB(0, 0, 128, 128),
);
mandrill.dispose();
codec.dispose();
});
@ -769,9 +774,11 @@ void _testForImageCodecs({required bool useBrowserImageDecoder}) {
canvas.drawImage(snapshot, ui.Offset.zero, CkPaint());
sb.addPicture(ui.Offset.zero, recorder.endRecording());
await matchSceneGolden(
'canvaskit_read_back_decoded_image_$mode.png', sb.build(),
region: const ui.Rect.fromLTRB(0, 0, 150, 150));
CanvasKitRenderer.instance.renderScene(sb.build(), implicitView);
await matchGoldenFile(
'canvaskit_read_back_decoded_image_$mode.png',
region: const ui.Rect.fromLTRB(0, 0, 150, 150),
);
}
image.dispose();

View File

@ -39,7 +39,7 @@ void testMain() {
sb.addPicture(ui.Offset.zero, picture);
final LayerScene scene = sb.build();
final LayerTree layerTree = scene.layerTree;
await renderScene(scene);
CanvasKitRenderer.instance.renderScene(scene, implicitView);
final ClipRectEngineLayer clipRect =
layerTree.rootLayer.debugLayers.single as ClipRectEngineLayer;
expect(clipRect.paintBounds, const ui.Rect.fromLTRB(15, 15, 30, 30));
@ -95,7 +95,7 @@ void testMain() {
final LayerScene scene = sb.build();
final LayerTree layerTree = scene.layerTree;
await renderScene(scene);
CanvasKitRenderer.instance.renderScene(scene, implicitView);
final ImageFilterEngineLayer imageFilterLayer =
layerTree.rootLayer.debugLayers.single as ImageFilterEngineLayer;

View File

@ -33,13 +33,13 @@ void testMain() {
});
test('can render into arbitrary views', () async {
await CanvasKitRenderer.instance.renderScene(scene, implicitView);
CanvasKitRenderer.instance.renderScene(scene, implicitView);
final EngineFlutterView anotherView = EngineFlutterView(
EnginePlatformDispatcher.instance, createDomElement('another-view'));
EnginePlatformDispatcher.instance.viewManager.registerView(anotherView);
await CanvasKitRenderer.instance.renderScene(scene, anotherView);
CanvasKitRenderer.instance.renderScene(scene, anotherView);
});
test('will error if trying to render into an unregistered view', () async {

View File

@ -21,13 +21,13 @@ void testMain() {
});
Future<DomImageBitmap> newBitmap(int width, int height) async {
return createImageBitmap(
return (await createImageBitmap(
createBlankDomImageData(width, height) as JSAny, (
x: 0,
y: 0,
width: width,
height: height,
));
)).toDart)! as DomImageBitmap;
}
// Regression test for https://github.com/flutter/flutter/issues/75286

View File

@ -21,9 +21,8 @@ Future<void> runFrameTimingsTest() async {
sceneBuilder
..pushOffset(0, 0)
..pop();
ui.PlatformDispatcher.instance.render(sceneBuilder.build()).then((_) {
frameDone.complete();
});
ui.PlatformDispatcher.instance.render(sceneBuilder.build());
frameDone.complete();
};
// Frame 1.

View File

@ -1,38 +0,0 @@
// 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:async';
import 'package:ui/src/engine.dart';
import 'package:ui/ui.dart' as ui;
// The scene that will be rendered in the next call to `onDrawFrame`.
ui.Scene? _sceneToRender;
// Completer that will complete when the call to render completes.
Completer<void>? _sceneCompleter;
/// Sets up rendering so that `onDrawFrame` will render the last requested
/// scene.
void setUpRenderingForTests() {
// Set `onDrawFrame` to call `renderer.renderScene`.
EnginePlatformDispatcher.instance.onDrawFrame = () {
if (_sceneToRender != null) {
EnginePlatformDispatcher.instance.render(_sceneToRender!).then<void>((_) {
_sceneCompleter?.complete();
}).catchError((Object error) {
_sceneCompleter?.completeError(error);
});
_sceneToRender = null;
}
};
}
/// Render the given [scene] in an `onDrawFrame` scope.
Future<void> renderScene(ui.Scene scene) {
_sceneToRender = scene;
_sceneCompleter = Completer<void>();
EnginePlatformDispatcher.instance.invokeOnDrawFrame();
return _sceneCompleter!.future;
}

View File

@ -11,7 +11,6 @@ import 'package:ui/ui.dart' as ui;
import 'package:ui/ui_web/src/ui_web.dart' as ui_web;
import 'fake_asset_manager.dart';
import 'rendering.dart';
void setUpUnitTests({
bool emulateTesterEnvironment = true,
@ -45,8 +44,6 @@ void setUpUnitTests({
const ui.Size(800 * devicePixelRatio, 600 * devicePixelRatio);
engine.scheduleFrameCallback = () {};
}
setUpRenderingForTests();
});
tearDownAll(() async {

View File

@ -26,13 +26,10 @@ class StubPictureRenderer implements PictureRenderer {
Future<DomImageBitmap> renderPicture(ScenePicture picture) async {
renderedPictures.add(picture);
final ui.Rect cullRect = picture.cullRect;
final DomImageBitmap bitmap =
await createImageBitmap(scratchCanvasElement as JSObject, (
x: 0,
y: 0,
width: cullRect.width.toInt(),
height: cullRect.height.toInt(),
));
final DomImageBitmap bitmap = (await createImageBitmap(
scratchCanvasElement as JSObject,
(x: 0, y: 0, width: cullRect.width.toInt(), height: cullRect.height.toInt())
).toDart)! as DomImageBitmap;
return bitmap;
}
@ -86,8 +83,7 @@ void testMain() {
debugOverrideDevicePixelRatio(null);
});
test('SceneView places platform view according to device-pixel ratio',
() async {
test('SceneView places platform view according to device-pixel ratio', () async {
debugOverrideDevicePixelRatio(2.0);
final PlatformView platformView = PlatformView(
@ -117,9 +113,7 @@ void testMain() {
debugOverrideDevicePixelRatio(null);
});
test(
'SceneView always renders most recent picture and skips intermediate pictures',
() async {
test('SceneView always renders most recent picture and skips intermediate pictures', () async {
final List<StubPicture> pictures = <StubPicture>[];
final List<Future<void>> renderFutures = <Future<void>>[];
for (int i = 1; i < 20; i++) {

View File

@ -13,7 +13,6 @@ import 'package:ui/src/engine.dart';
import 'package:ui/ui.dart' as ui;
import 'package:ui/ui_web/src/ui_web.dart' as ui_web;
import '../../common/rendering.dart';
import '../../common/test_initialization.dart';
import 'semantics_tester.dart';
@ -33,7 +32,6 @@ void main() {
Future<void> testMain() async {
await bootstrapAndRunApp();
setUpRenderingForTests();
runSemanticsTests();
}
@ -2528,7 +2526,7 @@ void _testPlatformView() {
width: 20,
height: 30,
);
await renderScene(sceneBuilder.build());
ui.PlatformDispatcher.instance.render(sceneBuilder.build());
final ui.SemanticsUpdateBuilder builder = ui.SemanticsUpdateBuilder();
final double dpr = EngineFlutterDisplay.instance.devicePixelRatio;

View File

@ -15,7 +15,6 @@ import 'package:ui/src/engine.dart';
import 'package:ui/ui.dart' as ui;
import '../../common/matchers.dart';
import '../../common/rendering.dart';
import '../../common/test_initialization.dart';
void main() {
@ -25,7 +24,6 @@ void main() {
void testMain() {
setUpAll(() async {
await bootstrapAndRunApp();
setUpRenderingForTests();
});
group('SceneBuilder', () {
@ -479,7 +477,7 @@ void testMain() {
// Pump an empty scene to reset it, otherwise the first frame will attempt
// to diff left-overs from a previous test, which results in unpredictable
// DOM mutations.
await renderScene(SurfaceSceneBuilder().build());
ui.PlatformDispatcher.instance.render(SurfaceSceneBuilder().build());
// Renders a `string` by breaking it up into individual characters and
// rendering each character into its own layer.

View File

@ -7,7 +7,6 @@ import 'package:test/test.dart';
import 'package:ui/src/engine.dart';
import 'package:ui/ui.dart' as ui;
import '../../common/rendering.dart';
import '../../common/test_initialization.dart';
import '../paragraph/helper.dart';
@ -792,7 +791,7 @@ Future<void> testMain() async {
expect(paragraph.height, 10);
});
test('Render after dispose', () async {
test('Render after dispose', () {
final ui.Paragraph paragraph = plain(ahemStyle, 'abc');
paragraph.layout(const ui.ParagraphConstraints(width: 30.8));
@ -807,7 +806,7 @@ Future<void> testMain() async {
builder.addPicture(ui.Offset.zero, picture);
final ui.Scene scene = builder.build();
await renderScene(scene);
ui.PlatformDispatcher.instance.render(scene);
picture.dispose();
scene.dispose();

View File

@ -318,7 +318,7 @@ Future<void> testMain() async {
image.src = url;
await completer.future;
final DomImageBitmap bitmap = await createImageBitmap(image as JSObject);
final DomImageBitmap bitmap = (await createImageBitmap(image as JSObject).toDart)! as DomImageBitmap;
expect(bitmap.width.toDartInt, 150);
expect(bitmap.height.toDartInt, 150);

View File

@ -11,8 +11,8 @@ import 'package:ui/ui.dart' as ui;
import 'package:ui/ui_web/src/ui_web.dart' as ui_web;
import 'package:web_engine_tester/golden_tester.dart';
import '../common/rendering.dart';
import '../common/test_initialization.dart';
import 'utils.dart';
void main() {
internalBootstrapBrowserTest(() => testMain);
@ -65,7 +65,7 @@ Future<void> testMain() async {
width: 50,
height: 50,
);
await renderScene(sb.build());
await renderer.renderScene(sb.build(), implicitView);
await matchGoldenFile('picture_platformview_overlap.png', region: region);
});
@ -97,7 +97,7 @@ Future<void> testMain() async {
);
sb.addPicture(const ui.Offset(125, 125), picture);
await renderScene(sb.build());
await renderer.renderScene(sb.build(), implicitView);
await matchGoldenFile('picture_platformview_sandwich.png', region: region);
});
@ -126,7 +126,7 @@ Future<void> testMain() async {
width: 50,
height: 50,
);
await renderScene(sb.build());
await renderer.renderScene(sb.build(), implicitView);
await matchGoldenFile('platformview_transformed.png', region: region);
});
@ -155,7 +155,7 @@ Future<void> testMain() async {
width: 50,
height: 50,
);
await renderScene(sb.build());
await renderer.renderScene(sb.build(), implicitView);
await matchGoldenFile('platformview_opacity.png', region: region);
});

View File

@ -10,7 +10,6 @@ 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';
@ -37,7 +36,7 @@ Future<void> testMain() async {
);
}));
await renderScene(sceneBuilder.build());
await renderer.renderScene(sceneBuilder.build(), implicitView);
await matchGoldenFile('scene_builder_centered_circle.png', region: region);
});
@ -61,7 +60,7 @@ Future<void> testMain() async {
);
}));
await renderScene(sceneBuilder.build());
await renderer.renderScene(sceneBuilder.build(), implicitView);
await matchGoldenFile('scene_builder_rotated_rounded_square.png', region: region);
});
@ -76,7 +75,7 @@ Future<void> testMain() async {
);
}));
await renderScene(sceneBuilder.build());
await renderer.renderScene(sceneBuilder.build(), implicitView);
await matchGoldenFile('scene_builder_circle_clip_rect.png', region: region);
});
@ -94,7 +93,7 @@ Future<void> testMain() async {
);
}));
await renderScene(sceneBuilder.build());
await renderer.renderScene(sceneBuilder.build(), implicitView);
await matchGoldenFile('scene_builder_circle_clip_rrect.png', region: region);
});
@ -110,7 +109,7 @@ Future<void> testMain() async {
);
}));
await renderScene(sceneBuilder.build());
await renderer.renderScene(sceneBuilder.build(), implicitView);
await matchGoldenFile('scene_builder_rectangle_clip_circular_path.png', region: region);
});
@ -138,7 +137,7 @@ Future<void> testMain() async {
);
}));
await renderScene(sceneBuilder.build());
await renderer.renderScene(sceneBuilder.build(), implicitView);
await matchGoldenFile('scene_builder_opacity_circles_on_square.png', region: region);
});
@ -178,7 +177,7 @@ Future<void> testMain() async {
);
}));
await renderScene(sceneBuilder.build());
await renderer.renderScene(sceneBuilder.build(), implicitView);
await matchGoldenFile('scene_builder_shader_mask.png', region: region);
}, skip: isFirefox && isHtml); // https://github.com/flutter/flutter/issues/86623
@ -210,7 +209,7 @@ Future<void> testMain() async {
);
}));
await renderScene(sceneBuilder.build());
await renderer.renderScene(sceneBuilder.build(), implicitView);
await matchGoldenFile('scene_builder_backdrop_filter.png', region: region);
});
@ -229,7 +228,7 @@ Future<void> testMain() async {
);
}));
await renderScene(sceneBuilder.build());
await renderer.renderScene(sceneBuilder.build(), implicitView);
await matchGoldenFile('scene_builder_image_filter.png', region: region);
});
@ -251,7 +250,7 @@ Future<void> testMain() async {
);
}));
await renderScene(sceneBuilder.build());
await renderer.renderScene(sceneBuilder.build(), implicitView);
await matchGoldenFile('scene_builder_color_filter.png', region: region);
});
});

View File

@ -9,8 +9,6 @@ import 'package:ui/src/engine/skwasm/skwasm_stub.dart'
if (dart.library.ffi) 'package:ui/src/engine/skwasm/skwasm_impl.dart';
import 'package:ui/ui.dart';
import '../common/rendering.dart';
Picture drawPicture(void Function(Canvas) drawCommands) {
final PictureRecorder recorder = PictureRecorder();
final Canvas canvas = Canvas(recorder);
@ -23,7 +21,7 @@ Future<void> drawPictureUsingCurrentRenderer(Picture picture) async {
final SceneBuilder sb = SceneBuilder();
sb.pushOffset(0, 0);
sb.addPicture(Offset.zero, picture);
await renderScene(sb.build());
await renderer.renderScene(sb.build(), implicitView);
}
/// Convenience getter for the implicit view.