Skip to content

Commit 63e8c62

Browse files
author
Harry Terkelsen
authored
Add ImageFilter and BackdropFilter to CanvasKit backend (flutter#13768)
* Implement ImageFilter.blur and BackdropFilter * update licenses file * Respond to review comments
1 parent 6d66993 commit 63e8c62

File tree

11 files changed

+82
-15
lines changed

11 files changed

+82
-15
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,7 @@ FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/color_filter.dart
361361
FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/engine_delegate.dart
362362
FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/fonts.dart
363363
FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/image.dart
364+
FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/image_filter.dart
364365
FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/initialization.dart
365366
FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/layer.dart
366367
FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/layer_scene_builder.dart

lib/web_ui/lib/src/engine.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ part 'engine/compositor/color_filter.dart';
2929
part 'engine/compositor/engine_delegate.dart';
3030
part 'engine/compositor/fonts.dart';
3131
part 'engine/compositor/image.dart';
32+
part 'engine/compositor/image_filter.dart';
3233
part 'engine/compositor/initialization.dart';
3334
part 'engine/compositor/layer.dart';
3435
part 'engine/compositor/layer_scene_builder.dart';

lib/web_ui/lib/src/engine/compositor/canvas.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,19 @@ class SkCanvas {
3333
'saveLayer', <js.JsObject>[makeSkRect(bounds), makeSkPaint(paint)]);
3434
}
3535

36+
int saveLayerWithFilter(ui.Rect bounds, ui.ImageFilter filter) {
37+
final SkImageFilter skImageFilter = filter;
38+
return skCanvas.callMethod(
39+
'saveLayer',
40+
<dynamic>[
41+
null,
42+
skImageFilter.skImageFilter,
43+
0,
44+
makeSkRect(bounds),
45+
],
46+
);
47+
}
48+
3649
void restore() {
3750
skCanvas.callMethod('restore');
3851
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
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+
part of engine;
6+
7+
/// The CanvasKit implementation of [ui.ImageFilter].
8+
///
9+
/// Currently only supports `blur`.
10+
class SkImageFilter implements ui.ImageFilter {
11+
js.JsObject skImageFilter;
12+
13+
SkImageFilter.blur({double sigmaX = 0.0, double sigmaY = 0.0}) {
14+
skImageFilter = canvasKit['SkImageFilter'].callMethod(
15+
'MakeBlur',
16+
<dynamic>[
17+
sigmaX,
18+
sigmaY,
19+
canvasKit['TileMode']['Clamp'],
20+
null,
21+
],
22+
);
23+
}
24+
}

lib/web_ui/lib/src/engine/compositor/initialization.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const bool experimentalUseSkia =
99
bool.fromEnvironment('FLUTTER_WEB_USE_SKIA', defaultValue: false);
1010

1111
/// The URL to use when downloading the CanvasKit script and associated wasm.
12-
const String canvasKitBaseUrl = 'https://unpkg.com/canvaskit-wasm@0.7.0/bin/';
12+
const String canvasKitBaseUrl = 'https://particles.skia.org/static/';
1313

1414
/// Initialize the Skia backend.
1515
///

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,19 @@ abstract class ContainerLayer extends Layer {
9393
}
9494
}
9595

96+
class BackdropFilterLayer extends ContainerLayer {
97+
final ui.ImageFilter _filter;
98+
99+
BackdropFilterLayer(this._filter);
100+
101+
@override
102+
void paint(PaintContext context) {
103+
context.canvas.saveLayerWithFilter(paintBounds, _filter);
104+
paintChildren(context);
105+
context.canvas.restore();
106+
}
107+
}
108+
96109
/// A layer that clips its child layers by a given [Path].
97110
class ClipPathLayer extends ContainerLayer {
98111
/// The path used to clip child layers.

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ class LayerSceneBuilder implements ui.SceneBuilder {
9292
@override
9393
ui.BackdropFilterEngineLayer pushBackdropFilter(ui.ImageFilter filter,
9494
{ui.EngineLayer oldLayer}) {
95-
throw UnimplementedError();
95+
pushLayer(BackdropFilterLayer(filter));
96+
return null;
9697
}
9798

9899
@override

lib/web_ui/lib/src/engine/compositor/util.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,12 @@ js.JsObject makeSkPaint(ui.Paint paint) {
156156
skPaint.callMethod('setMaskFilter', <js.JsObject>[skMaskFilter]);
157157
}
158158

159+
if (paint.imageFilter != null) {
160+
final SkImageFilter skImageFilter = paint.imageFilter;
161+
skPaint.callMethod(
162+
'setImageFilter', <js.JsObject>[skImageFilter.skImageFilter]);
163+
}
164+
159165
if (paint.colorFilter != null) {
160166
EngineColorFilter engineFilter = paint.colorFilter;
161167
SkColorFilter skFilter = engineFilter._toSkColorFilter();

lib/web_ui/lib/src/engine/shader.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,13 @@ class GradientConical extends EngineGradient {
231231
throw UnimplementedError();
232232
}
233233
}
234+
235+
/// Backend implementation of [ui.ImageFilter].
236+
///
237+
/// Currently only `blur` is supported.
238+
class EngineImageFilter implements ui.ImageFilter {
239+
EngineImageFilter.blur({this.sigmaX = 0.0, this.sigmaY = 0.0});
240+
241+
final double sigmaX;
242+
final double sigmaY;
243+
}

lib/web_ui/lib/src/engine/surface/backdrop_filter.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,12 @@ class PersistedBackdropFilter extends PersistedContainerSurface
8585
..backgroundColor = '#000'
8686
..opacity = '0.2';
8787
} else {
88+
final EngineImageFilter engineFilter = filter;
8889
// CSS uses pixel radius for blur. Flutter & SVG use sigma parameters. For
8990
// Gaussian blur with standard deviation (normal distribution),
9091
// the blur will fall within 2 * sigma pixels.
9192
domRenderer.setElementStyle(_filterElement, 'backdrop-filter',
92-
'blur(${math.max(filter.sigmaX, filter.sigmaY) * 2}px)');
93+
'blur(${math.max(engineFilter.sigmaX, engineFilter.sigmaY) * 2}px)');
9394
}
9495
}
9596

0 commit comments

Comments
 (0)