Skip to content

Commit 25293df

Browse files
author
Harry Terkelsen
authored
Implement pushColorFilter in CanvasKit (flutter#22838)
* Implement pushColorFilter in CanvasKit * Add test * Update goldens lock
1 parent 5d51422 commit 25293df

File tree

5 files changed

+115
-6
lines changed

5 files changed

+115
-6
lines changed

lib/web_ui/dev/goldens_lock.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
repository: https://github.com/flutter/goldens.git
2-
revision: ac75f12c6e93461369e1391da6cc20bf8cb08829
2+
revision: c808c28c81b6c3143ae969e8c49bed4a6d49aabb

lib/web_ui/lib/src/engine/canvaskit/layer.dart

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -449,8 +449,8 @@ class PhysicalShapeLayer extends ContainerLayer
449449
assert(needsPainting);
450450

451451
if (_elevation != 0) {
452-
drawShadow(paintContext.leafNodesCanvas!, _path, _shadowColor!, _elevation,
453-
_color.alpha != 0xff);
452+
drawShadow(paintContext.leafNodesCanvas!, _path, _shadowColor!,
453+
_elevation, _color.alpha != 0xff);
454454
}
455455

456456
final CkPaint paint = CkPaint()..color = _color;
@@ -497,6 +497,25 @@ class PhysicalShapeLayer extends ContainerLayer
497497
}
498498
}
499499

500+
/// A layer which contains a [ui.ColorFilter].
501+
class ColorFilterLayer extends ContainerLayer {
502+
ColorFilterLayer(this.filter);
503+
504+
final ui.ColorFilter filter;
505+
506+
@override
507+
void paint(PaintContext paintContext) {
508+
assert(needsPainting);
509+
510+
CkPaint paint = CkPaint();
511+
paint.colorFilter = filter;
512+
513+
paintContext.internalNodesCanvas.saveLayer(paintBounds, paint);
514+
paintChildren(paintContext);
515+
paintContext.internalNodesCanvas.restore();
516+
}
517+
}
518+
500519
/// A layer which renders a platform view (an HTML element in this case).
501520
class PlatformViewLayer extends Layer {
502521
PlatformViewLayer(this.viewId, this.offset, this.width, this.height);

lib/web_ui/lib/src/engine/canvaskit/layer_scene_builder.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,12 +138,13 @@ class LayerSceneBuilder implements ui.SceneBuilder {
138138
}
139139

140140
@override
141-
ui.ColorFilterEngineLayer pushColorFilter(
141+
ui.ColorFilterEngineLayer? pushColorFilter(
142142
ui.ColorFilter filter, {
143143
ui.ColorFilterEngineLayer? oldLayer,
144144
}) {
145145
assert(filter != null); // ignore: unnecessary_null_comparison
146-
throw UnimplementedError();
146+
pushLayer(ColorFilterLayer(filter));
147+
return null;
147148
}
148149

149150
ui.ImageFilterEngineLayer? pushImageFilter(
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
// @dart = 2.12
6+
import 'package:test/bootstrap/browser.dart';
7+
import 'package:test/test.dart';
8+
import 'package:ui/src/engine.dart';
9+
import 'package:ui/ui.dart' as ui;
10+
11+
import 'package:web_engine_tester/golden_tester.dart';
12+
13+
import 'common.dart';
14+
15+
void main() {
16+
internalBootstrapBrowserTest(() => testMain);
17+
}
18+
19+
const ui.Rect region = const ui.Rect.fromLTRB(0, 0, 500, 250);
20+
21+
Future<void> matchSceneGolden(String goldenFile, LayerScene scene,
22+
{bool write = false}) async {
23+
final EnginePlatformDispatcher dispatcher =
24+
ui.window.platformDispatcher as EnginePlatformDispatcher;
25+
dispatcher.rasterizer!.draw(scene.layerTree);
26+
await matchGoldenFile(goldenFile, region: region, write: write);
27+
}
28+
29+
void testMain() {
30+
group('ColorFilter', () {
31+
setUpCanvasKitTest();
32+
33+
test('ColorFilter.matrix applies a color filter', () async {
34+
final LayerSceneBuilder builder = LayerSceneBuilder();
35+
36+
builder.pushOffset(0, 0);
37+
38+
// Draw a red circle and apply it to the scene.
39+
final CkPictureRecorder recorder = CkPictureRecorder();
40+
final CkCanvas canvas = recorder.beginRecording(region);
41+
42+
canvas.drawCircle(
43+
ui.Offset(75, 125),
44+
50,
45+
CkPaint()..color = ui.Color.fromARGB(255, 255, 0, 0),
46+
);
47+
final CkPicture redCircle = recorder.endRecording();
48+
49+
builder.addPicture(ui.Offset.zero, redCircle);
50+
51+
// Apply a "greyscale" color filter.
52+
builder.pushColorFilter(ui.ColorFilter.matrix([
53+
0.2126, 0.7152, 0.0722, 0, 0, //
54+
0.2126, 0.7152, 0.0722, 0, 0, //
55+
0.2126, 0.7152, 0.0722, 0, 0, //
56+
0, 0, 0, 1, 0, //
57+
]));
58+
59+
// Draw another red circle and apply it to the scene.
60+
// This one should be grey since we have the color filter.
61+
final CkPictureRecorder recorder2 = CkPictureRecorder();
62+
final CkCanvas canvas2 = recorder2.beginRecording(region);
63+
64+
canvas2.drawCircle(
65+
ui.Offset(425, 125),
66+
50,
67+
CkPaint()..color = ui.Color.fromARGB(255, 255, 0, 0),
68+
);
69+
final CkPicture greyCircle = recorder2.endRecording();
70+
71+
builder.addPicture(ui.Offset.zero, greyCircle);
72+
73+
await matchSceneGolden('canvaskit_colorfilter.png', builder.build());
74+
});
75+
// TODO: https://github.com/flutter/flutter/issues/60040
76+
// TODO: https://github.com/flutter/flutter/issues/71520
77+
}, skip: isIosSafari || isFirefox);
78+
}

lib/web_ui/test/canvaskit/scene_test.dart

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,17 @@ void testMain() {
4949
final ui.Image sceneImage = await scene.toImage(100, 100);
5050
expect(sceneImage, isA<CkImage>());
5151
});
52-
// TODO: https://github.com/flutter/flutter/issues/60040
52+
53+
test('pushColorFilter does not throw', () async {
54+
final ui.SceneBuilder builder = ui.SceneBuilder();
55+
expect(builder, isA<LayerSceneBuilder>());
56+
57+
builder.pushOffset(0, 0);
58+
builder.pushColorFilter(ui.ColorFilter.srgbToLinearGamma());
59+
60+
final ui.Scene scene = builder.build();
61+
expect(scene, isNotNull);
62+
});
63+
// TODO: https://github.com/flutter/flutter/issues/60040
5364
}, skip: isIosSafari);
5465
}

0 commit comments

Comments
 (0)