Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/web_ui/dev/goldens_lock.yaml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
repository: https://github.com/flutter/goldens.git
revision: ac75f12c6e93461369e1391da6cc20bf8cb08829
revision: c808c28c81b6c3143ae969e8c49bed4a6d49aabb
23 changes: 21 additions & 2 deletions lib/web_ui/lib/src/engine/canvaskit/layer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -449,8 +449,8 @@ class PhysicalShapeLayer extends ContainerLayer
assert(needsPainting);

if (_elevation != 0) {
drawShadow(paintContext.leafNodesCanvas!, _path, _shadowColor!, _elevation,
_color.alpha != 0xff);
drawShadow(paintContext.leafNodesCanvas!, _path, _shadowColor!,
_elevation, _color.alpha != 0xff);
}

final CkPaint paint = CkPaint()..color = _color;
Expand Down Expand Up @@ -497,6 +497,25 @@ class PhysicalShapeLayer extends ContainerLayer
}
}

/// A layer which contains a [ui.ColorFilter].
class ColorFilterLayer extends ContainerLayer {
ColorFilterLayer(this.filter);

final ui.ColorFilter filter;

@override
void paint(PaintContext paintContext) {
assert(needsPainting);

CkPaint paint = CkPaint();
paint.colorFilter = filter;

paintContext.internalNodesCanvas.saveLayer(paintBounds, paint);
paintChildren(paintContext);
paintContext.internalNodesCanvas.restore();
}
}

/// A layer which renders a platform view (an HTML element in this case).
class PlatformViewLayer extends Layer {
PlatformViewLayer(this.viewId, this.offset, this.width, this.height);
Expand Down
5 changes: 3 additions & 2 deletions lib/web_ui/lib/src/engine/canvaskit/layer_scene_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -138,12 +138,13 @@ class LayerSceneBuilder implements ui.SceneBuilder {
}

@override
ui.ColorFilterEngineLayer pushColorFilter(
ui.ColorFilterEngineLayer? pushColorFilter(
ui.ColorFilter filter, {
ui.ColorFilterEngineLayer? oldLayer,
}) {
assert(filter != null); // ignore: unnecessary_null_comparison
throw UnimplementedError();
pushLayer(ColorFilterLayer(filter));
return null;
}

ui.ImageFilterEngineLayer? pushImageFilter(
Expand Down
78 changes: 78 additions & 0 deletions lib/web_ui/test/canvaskit/color_filter_golden_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// 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.

// @dart = 2.12
import 'package:test/bootstrap/browser.dart';
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() {
internalBootstrapBrowserTest(() => testMain);
}

const ui.Rect region = const ui.Rect.fromLTRB(0, 0, 500, 250);

Future<void> matchSceneGolden(String goldenFile, LayerScene scene,
{bool write = false}) async {
final EnginePlatformDispatcher dispatcher =
ui.window.platformDispatcher as EnginePlatformDispatcher;
dispatcher.rasterizer!.draw(scene.layerTree);
await matchGoldenFile(goldenFile, region: region, write: write);
}

void testMain() {
group('ColorFilter', () {
setUpCanvasKitTest();

test('ColorFilter.matrix applies a color filter', () async {
final LayerSceneBuilder builder = LayerSceneBuilder();

builder.pushOffset(0, 0);

// Draw a red circle and apply it to the scene.
final CkPictureRecorder recorder = CkPictureRecorder();
final CkCanvas canvas = recorder.beginRecording(region);

canvas.drawCircle(
ui.Offset(75, 125),
50,
CkPaint()..color = ui.Color.fromARGB(255, 255, 0, 0),
);
final CkPicture redCircle = recorder.endRecording();

builder.addPicture(ui.Offset.zero, redCircle);

// Apply a "greyscale" color filter.
builder.pushColorFilter(ui.ColorFilter.matrix([
0.2126, 0.7152, 0.0722, 0, 0, //
0.2126, 0.7152, 0.0722, 0, 0, //
0.2126, 0.7152, 0.0722, 0, 0, //
0, 0, 0, 1, 0, //
]));

// Draw another red circle and apply it to the scene.
// This one should be grey since we have the color filter.
final CkPictureRecorder recorder2 = CkPictureRecorder();
final CkCanvas canvas2 = recorder2.beginRecording(region);

canvas2.drawCircle(
ui.Offset(425, 125),
50,
CkPaint()..color = ui.Color.fromARGB(255, 255, 0, 0),
);
final CkPicture greyCircle = recorder2.endRecording();

builder.addPicture(ui.Offset.zero, greyCircle);

await matchSceneGolden('canvaskit_colorfilter.png', builder.build());
});
// TODO: https://github.com/flutter/flutter/issues/60040
// TODO: https://github.com/flutter/flutter/issues/71520
}, skip: isIosSafari || isFirefox);
}
13 changes: 12 additions & 1 deletion lib/web_ui/test/canvaskit/scene_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,17 @@ void testMain() {
final ui.Image sceneImage = await scene.toImage(100, 100);
expect(sceneImage, isA<CkImage>());
});
// TODO: https://github.com/flutter/flutter/issues/60040

test('pushColorFilter does not throw', () async {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bonus points for making it a screenshot test. To do that, simply rename the file to scene_golden_test.dart and use golden_tester.dart like normal (example).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

although the test would need to be skipped outside chrome.

final ui.SceneBuilder builder = ui.SceneBuilder();
expect(builder, isA<LayerSceneBuilder>());

builder.pushOffset(0, 0);
builder.pushColorFilter(ui.ColorFilter.srgbToLinearGamma());

final ui.Scene scene = builder.build();
expect(scene, isNotNull);
});
// TODO: https://github.com/flutter/flutter/issues/60040
}, skip: isIosSafari);
}