From 72531283bfbda7e73f0c1cc8bcd45fe613493634 Mon Sep 17 00:00:00 2001 From: Jim Graham Date: Wed, 5 May 2021 23:12:20 -0700 Subject: [PATCH 1/3] support ImageFilter.matrix on web --- .../src/engine/canvaskit/image_filter.dart | 35 +++++++++++++- .../lib/src/engine/html/backdrop_filter.dart | 4 +- .../lib/src/engine/html/image_filter.dart | 3 +- .../lib/src/engine/html/scene_builder.dart | 2 +- .../lib/src/engine/html/shaders/shader.dart | 47 +++++++++++++++++-- lib/web_ui/lib/src/engine/util.dart | 12 ++--- lib/web_ui/lib/src/ui/painting.dart | 14 ++++-- .../engine/compositing_golden_test.dart | 21 ++++++++- 8 files changed, 117 insertions(+), 21 deletions(-) diff --git a/lib/web_ui/lib/src/engine/canvaskit/image_filter.dart b/lib/web_ui/lib/src/engine/canvaskit/image_filter.dart index 7490fcf55862b..3aad47d26b4ab 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/image_filter.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/image_filter.dart @@ -22,7 +22,7 @@ abstract class CkManagedSkImageFilterConvertible /// The CanvasKit implementation of [ui.ImageFilter]. /// -/// Currently only supports `blur`. +/// Currently only supports `blur`, `matrix`, and ColorFilters. abstract class CkImageFilter extends ManagedSkiaObject implements CkManagedSkImageFilterConvertible { factory CkImageFilter.blur( @@ -31,6 +31,9 @@ abstract class CkImageFilter extends ManagedSkiaObject required ui.TileMode tileMode}) = _CkBlurImageFilter; factory CkImageFilter.color({required CkColorFilter colorFilter}) = CkColorFilterImageFilter; + factory CkImageFilter.matrix( + {required Float64List matrix, + required ui.FilterQuality filterQuality}) = _CkMatrixImageFilter; CkImageFilter._(); @@ -126,3 +129,33 @@ class _CkBlurImageFilter extends CkImageFilter { return 'ImageFilter.blur($sigmaX, $sigmaY, $_modeString)'; } } + +class _CkMatrixImageFilter extends CkImageFilter { + _CkMatrixImageFilter({ required this.matrix, required this.filterQuality }) : super._(); + + Float64List matrix; + ui.FilterQuality filterQuality; + + SkImageFilter _initSkiaObject() { + return canvasKit.ImageFilter.MakeMatrixTransform( + toSkMatrixFromFloat64(matrix), + toSkFilterQuality(filterQuality), + null, + ); + } + + @override + bool operator ==(Object other) { + if (other.runtimeType != runtimeType) + return false; + return other is _CkMatrixImageFilter + && other.filterQuality == filterQuality + && _listEquals(other.matrix, matrix); + } + + @override + int get hashCode => ui.hashValues(filterQuality, ui.hashList(matrix)); + + @override + String toString() => 'ImageFilter.matrix($matrix, $filterQuality)'; +} diff --git a/lib/web_ui/lib/src/engine/html/backdrop_filter.dart b/lib/web_ui/lib/src/engine/html/backdrop_filter.dart index 625d73dacfef4..191d6bfc6f8b8 100644 --- a/lib/web_ui/lib/src/engine/html/backdrop_filter.dart +++ b/lib/web_ui/lib/src/engine/html/backdrop_filter.dart @@ -113,9 +113,9 @@ class PersistedBackdropFilter extends PersistedContainerSurface // the blur will fall within 2 * sigma pixels. if (browserEngine == BrowserEngine.webkit) { DomRenderer.setElementStyle(_filterElement!, '-webkit-backdrop-filter', - _imageFilterToCss(filter)); + filter._filterAttribute); } - DomRenderer.setElementStyle(_filterElement!, 'backdrop-filter', _imageFilterToCss(filter)); + DomRenderer.setElementStyle(_filterElement!, 'backdrop-filter', filter._filterAttribute); } } diff --git a/lib/web_ui/lib/src/engine/html/image_filter.dart b/lib/web_ui/lib/src/engine/html/image_filter.dart index bd46482d60eef..2f2c87c2b2ccb 100644 --- a/lib/web_ui/lib/src/engine/html/image_filter.dart +++ b/lib/web_ui/lib/src/engine/html/image_filter.dart @@ -18,7 +18,8 @@ class PersistedImageFilter extends PersistedContainerSurface @override void apply() { - rootElement!.style.filter = _imageFilterToCss(filter as EngineImageFilter); + rootElement!.style.filter = (filter as EngineImageFilter)._filterAttribute; + rootElement!.style.transform = (filter as EngineImageFilter)._transformAttribute; } @override diff --git a/lib/web_ui/lib/src/engine/html/scene_builder.dart b/lib/web_ui/lib/src/engine/html/scene_builder.dart index bb6801fa628b8..bc87571700eaf 100644 --- a/lib/web_ui/lib/src/engine/html/scene_builder.dart +++ b/lib/web_ui/lib/src/engine/html/scene_builder.dart @@ -586,6 +586,6 @@ class SurfaceSceneBuilder implements ui.SceneBuilder { // HTML only supports a single radius, but Flutter ImageFilter supports separate // horizontal and vertical radii. The best approximation we can provide is to // average the two radii together for a single compromise value. -String _imageFilterToCss(EngineImageFilter filter) { +String _imageFilterToCss(_BlurEngineImageFilter filter) { return 'blur(${(filter.sigmaX + filter.sigmaY) / 2}px)'; } diff --git a/lib/web_ui/lib/src/engine/html/shaders/shader.dart b/lib/web_ui/lib/src/engine/html/shaders/shader.dart index dcadd6587d751..fcb4f58694a3d 100644 --- a/lib/web_ui/lib/src/engine/html/shaders/shader.dart +++ b/lib/web_ui/lib/src/engine/html/shaders/shader.dart @@ -660,16 +660,30 @@ class GradientConical extends GradientRadial { /// Backend implementation of [ui.ImageFilter]. /// -/// Currently only `blur` is supported. -class EngineImageFilter implements ui.ImageFilter { - EngineImageFilter.blur({this.sigmaX = 0.0, this.sigmaY = 0.0}); +/// Currently only `blur` and `matrix` are supported. +abstract class EngineImageFilter implements ui.ImageFilter { + factory EngineImageFilter.blur({ required double sigmaX, required double sigmaY }) = _BlurEngineImageFilter; + factory EngineImageFilter.matrix({ required Float64List matrix }) = _MatrixEngineImageFilter; + + EngineImageFilter._(); + + String get _filterAttribute => ''; + String get _transformAttribute => ''; +} + +class _BlurEngineImageFilter extends EngineImageFilter { + _BlurEngineImageFilter({ this.sigmaX = 0.0, this.sigmaY = 0.0 }) : super._(); final double sigmaX; final double sigmaY; + String get _filterAttribute => _imageFilterToCss(this); + @override bool operator ==(Object other) { - return other is EngineImageFilter && + if (other.runtimeType != runtimeType) + return false; + return other is _BlurEngineImageFilter && other.sigmaX == sigmaX && other.sigmaY == sigmaY; } @@ -682,3 +696,28 @@ class EngineImageFilter implements ui.ImageFilter { return 'ImageFilter.blur($sigmaX, $sigmaY)'; } } + +class _MatrixEngineImageFilter extends EngineImageFilter { + _MatrixEngineImageFilter({ required this.matrix }) : super._(); + + final Float64List matrix; + + String get _transformAttribute => float64ListToCssTransform(matrix); + + @override + bool operator ==(Object other) { + if (other.runtimeType != runtimeType) + return false; + return other is _MatrixEngineImageFilter + // && other.filterQuality == filterQuality + && _listEquals(other.matrix, matrix); + } + + @override + int get hashCode => ui.hashList(matrix); + + @override + String toString() { + return 'ImageFilter.matrix($matrix)'; + } +} diff --git a/lib/web_ui/lib/src/engine/util.dart b/lib/web_ui/lib/src/engine/util.dart index 2b742702a9b1e..8df961341ce36 100644 --- a/lib/web_ui/lib/src/engine/util.dart +++ b/lib/web_ui/lib/src/engine/util.dart @@ -81,7 +81,7 @@ void setElementTransform(html.Element element, Float32List matrix4) { /// See also: /// * https://github.com/flutter/flutter/issues/32274 /// * https://bugs.chromium.org/p/chromium/issues/detail?id=1040222 -String float64ListToCssTransform(Float32List matrix) { +String float64ListToCssTransform(List matrix) { assert(matrix.length == 16); final TransformKind transformKind = transformKindOf(matrix); if (transformKind == TransformKind.transform2d) { @@ -113,9 +113,9 @@ enum TransformKind { } /// Detects the kind of transform the [matrix] performs. -TransformKind transformKindOf(Float32List matrix) { +TransformKind transformKindOf(List matrix) { assert(matrix.length == 16); - final Float32List m = matrix; + final List m = matrix; // If matrix contains scaling, rotation, z translation or // perspective transform, it is not considered simple. @@ -171,15 +171,15 @@ bool isIdentityFloat32ListTransform(Float32List matrix) { /// permitted. However, it is inefficient to construct a matrix for an identity /// transform. Consider removing the CSS `transform` property from elements /// that apply identity transform. -String float64ListToCssTransform2d(Float32List matrix) { +String float64ListToCssTransform2d(List matrix) { assert(transformKindOf(matrix) != TransformKind.complex); return 'matrix(${matrix[0]},${matrix[1]},${matrix[4]},${matrix[5]},${matrix[12]},${matrix[13]})'; } /// Converts [matrix] to a 3D CSS transform value. -String float64ListToCssTransform3d(Float32List matrix) { +String float64ListToCssTransform3d(List matrix) { assert(matrix.length == 16); - final Float32List m = matrix; + final List m = matrix; if (m[0] == 1.0 && m[1] == 0.0 && m[2] == 0.0 && diff --git a/lib/web_ui/lib/src/ui/painting.dart b/lib/web_ui/lib/src/ui/painting.dart index 94a1214156e31..b96cd77fba20f 100644 --- a/lib/web_ui/lib/src/ui/painting.dart +++ b/lib/web_ui/lib/src/ui/painting.dart @@ -399,14 +399,18 @@ class ImageFilter { if (engine.useCanvasKit) { return engine.CkImageFilter.blur(sigmaX: sigmaX, sigmaY: sigmaY, tileMode: tileMode); } + // TODO(flutter_web): implement BlendMode. return engine.EngineImageFilter.blur(sigmaX: sigmaX, sigmaY: sigmaY); } - ImageFilter.matrix(Float64List matrix4, {FilterQuality filterQuality = FilterQuality.low}) { - // TODO(flutter_web): add implementation. - throw UnimplementedError('ImageFilter.matrix not implemented for web platform.'); - // if (matrix4.length != 16) - // throw ArgumentError('"matrix4" must have 16 entries.'); + factory ImageFilter.matrix(Float64List matrix4, {FilterQuality filterQuality = FilterQuality.low}) { + if (matrix4.length != 16) + throw ArgumentError('"matrix4" must have 16 entries.'); + if (engine.useCanvasKit) { + return engine.CkImageFilter.matrix(matrix: matrix4, filterQuality: filterQuality); + } + // TODO(flutter_web): implement FilterQuality. + return engine.EngineImageFilter.matrix(matrix: matrix4); } ImageFilter.compose({required ImageFilter outer, required ImageFilter inner}) { diff --git a/lib/web_ui/test/golden_tests/engine/compositing_golden_test.dart b/lib/web_ui/test/golden_tests/engine/compositing_golden_test.dart index 6fd091aff8dd9..4d9d7510971ae 100644 --- a/lib/web_ui/test/golden_tests/engine/compositing_golden_test.dart +++ b/lib/web_ui/test/golden_tests/engine/compositing_golden_test.dart @@ -361,7 +361,7 @@ void testMain() async { viewElement6.remove(); }); - test('pushImageFilter', () async { + test('pushImageFilter blur', () async { final SurfaceSceneBuilder builder = SurfaceSceneBuilder(); builder.pushImageFilter( ImageFilter.blur(sigmaX: 1, sigmaY: 3), @@ -374,6 +374,25 @@ void testMain() async { await matchGoldenFile('compositing_image_filter.png', region: region); }); + test('pushImageFilter matrix', () async { + final SurfaceSceneBuilder builder = SurfaceSceneBuilder(); + builder.pushImageFilter( + ImageFilter.matrix( + ( + Matrix4.identity() + ..translate(40, 10) + ..rotateZ(math.pi / 6) + ..scale(0.75, 0.75) + ).toFloat64()), + ); + _drawTestPicture(builder); + builder.pop(); + + html.document.body.append(builder.build().webOnlyRootElement); + + await matchGoldenFile('compositing_image_filter_matrix.png', region: region); + }); + group('Cull rect computation', () { _testCullRectComputation(); }); From 5e104cbf5b0d1bdb81f4c7fc4724cd77c10d438c Mon Sep 17 00:00:00 2001 From: Jim Graham Date: Mon, 17 May 2021 12:39:33 -0700 Subject: [PATCH 2/3] make web properties final and write constructor/== tests --- .../src/engine/canvaskit/image_filter.dart | 8 +- .../lib/src/engine/html/shaders/shader.dart | 39 ++++++--- lib/web_ui/lib/src/ui/painting.dart | 6 +- .../surface/filters/image_filter_test.dart | 79 +++++++++++++++++++ 4 files changed, 114 insertions(+), 18 deletions(-) create mode 100644 lib/web_ui/test/engine/surface/filters/image_filter_test.dart diff --git a/lib/web_ui/lib/src/engine/canvaskit/image_filter.dart b/lib/web_ui/lib/src/engine/canvaskit/image_filter.dart index 3aad47d26b4ab..bdd3f0cfdd083 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/image_filter.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/image_filter.dart @@ -131,10 +131,12 @@ class _CkBlurImageFilter extends CkImageFilter { } class _CkMatrixImageFilter extends CkImageFilter { - _CkMatrixImageFilter({ required this.matrix, required this.filterQuality }) : super._(); + _CkMatrixImageFilter({ required Float64List matrix, required this.filterQuality }) + : this.matrix = Float64List.fromList(matrix), + super._(); - Float64List matrix; - ui.FilterQuality filterQuality; + final Float64List matrix; + final ui.FilterQuality filterQuality; SkImageFilter _initSkiaObject() { return canvasKit.ImageFilter.MakeMatrixTransform( diff --git a/lib/web_ui/lib/src/engine/html/shaders/shader.dart b/lib/web_ui/lib/src/engine/html/shaders/shader.dart index fcb4f58694a3d..89886777578c8 100644 --- a/lib/web_ui/lib/src/engine/html/shaders/shader.dart +++ b/lib/web_ui/lib/src/engine/html/shaders/shader.dart @@ -662,8 +662,16 @@ class GradientConical extends GradientRadial { /// /// Currently only `blur` and `matrix` are supported. abstract class EngineImageFilter implements ui.ImageFilter { - factory EngineImageFilter.blur({ required double sigmaX, required double sigmaY }) = _BlurEngineImageFilter; - factory EngineImageFilter.matrix({ required Float64List matrix }) = _MatrixEngineImageFilter; + factory EngineImageFilter.blur({ + required double sigmaX, + required double sigmaY, + required ui.TileMode tileMode, + }) = _BlurEngineImageFilter; + + factory EngineImageFilter.matrix({ + required Float64List matrix, + required ui.FilterQuality filterQuality, + }) = _MatrixEngineImageFilter; EngineImageFilter._(); @@ -672,11 +680,13 @@ abstract class EngineImageFilter implements ui.ImageFilter { } class _BlurEngineImageFilter extends EngineImageFilter { - _BlurEngineImageFilter({ this.sigmaX = 0.0, this.sigmaY = 0.0 }) : super._(); + _BlurEngineImageFilter({ this.sigmaX = 0.0, this.sigmaY = 0.0, this.tileMode = ui.TileMode.clamp }) : super._(); final double sigmaX; final double sigmaY; + final ui.TileMode tileMode; + // TODO(flutter_web): implement TileMode. String get _filterAttribute => _imageFilterToCss(this); @override @@ -684,40 +694,45 @@ class _BlurEngineImageFilter extends EngineImageFilter { if (other.runtimeType != runtimeType) return false; return other is _BlurEngineImageFilter && + other.tileMode == tileMode && other.sigmaX == sigmaX && other.sigmaY == sigmaY; } @override - int get hashCode => ui.hashValues(sigmaX, sigmaY); + int get hashCode => ui.hashValues(sigmaX, sigmaY, tileMode); @override String toString() { - return 'ImageFilter.blur($sigmaX, $sigmaY)'; + return 'ImageFilter.blur($sigmaX, $sigmaY, $tileMode)'; } } class _MatrixEngineImageFilter extends EngineImageFilter { - _MatrixEngineImageFilter({ required this.matrix }) : super._(); + _MatrixEngineImageFilter({ required Float64List matrix, required this.filterQuality }) + : webMatrix = Float64List.fromList(matrix), + super._(); - final Float64List matrix; + final Float64List webMatrix; + final ui.FilterQuality filterQuality; - String get _transformAttribute => float64ListToCssTransform(matrix); + // TODO(flutter_web): implement FilterQuality. + String get _transformAttribute => float64ListToCssTransform(webMatrix); @override bool operator ==(Object other) { if (other.runtimeType != runtimeType) return false; return other is _MatrixEngineImageFilter - // && other.filterQuality == filterQuality - && _listEquals(other.matrix, matrix); + && other.filterQuality == filterQuality + && _listEquals(other.webMatrix, webMatrix); } @override - int get hashCode => ui.hashList(matrix); + int get hashCode => ui.hashValues(ui.hashList(webMatrix), filterQuality); @override String toString() { - return 'ImageFilter.matrix($matrix)'; + return 'ImageFilter.matrix($webMatrix, $filterQuality)'; } } diff --git a/lib/web_ui/lib/src/ui/painting.dart b/lib/web_ui/lib/src/ui/painting.dart index b96cd77fba20f..b42ee71725852 100644 --- a/lib/web_ui/lib/src/ui/painting.dart +++ b/lib/web_ui/lib/src/ui/painting.dart @@ -399,8 +399,8 @@ class ImageFilter { if (engine.useCanvasKit) { return engine.CkImageFilter.blur(sigmaX: sigmaX, sigmaY: sigmaY, tileMode: tileMode); } - // TODO(flutter_web): implement BlendMode. - return engine.EngineImageFilter.blur(sigmaX: sigmaX, sigmaY: sigmaY); + // TODO(flutter_web): implement TileMode. + return engine.EngineImageFilter.blur(sigmaX: sigmaX, sigmaY: sigmaY, tileMode: tileMode); } factory ImageFilter.matrix(Float64List matrix4, {FilterQuality filterQuality = FilterQuality.low}) { @@ -410,7 +410,7 @@ class ImageFilter { return engine.CkImageFilter.matrix(matrix: matrix4, filterQuality: filterQuality); } // TODO(flutter_web): implement FilterQuality. - return engine.EngineImageFilter.matrix(matrix: matrix4); + return engine.EngineImageFilter.matrix(matrix: matrix4, filterQuality: filterQuality); } ImageFilter.compose({required ImageFilter outer, required ImageFilter inner}) { diff --git a/lib/web_ui/test/engine/surface/filters/image_filter_test.dart b/lib/web_ui/test/engine/surface/filters/image_filter_test.dart new file mode 100644 index 0000000000000..147594dd35df8 --- /dev/null +++ b/lib/web_ui/test/engine/surface/filters/image_filter_test.dart @@ -0,0 +1,79 @@ +// 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:typed_data'; + +import 'package:test/bootstrap/browser.dart'; +import 'package:test/test.dart'; +import 'package:ui/src/engine.dart'; +import 'package:ui/ui.dart'; + +void main() { + internalBootstrapBrowserTest(() => testMain); +} + +void testMain() { + group('ImageFilter constructors', () { + test('matrix is copied', () { + Matrix4 matrix = Matrix4.identity(); + Float64List storage = matrix.toFloat64(); + ImageFilter filter1 = ImageFilter.matrix(storage); + storage[0] = 2.0; + ImageFilter filter2 = ImageFilter.matrix(storage); + expect(filter1, filter1); + expect(filter2, filter2); + expect(filter1, isNot(equals(filter2))); + expect(filter2, isNot(equals(filter1))); + }); + + test('matrix tests all values on ==', () { + Matrix4 matrix = Matrix4.identity(); + Float64List storage = matrix.toFloat64(); + ImageFilter filter1a = ImageFilter.matrix(storage, filterQuality: FilterQuality.none); + ImageFilter filter1b = ImageFilter.matrix(storage, filterQuality: FilterQuality.high); + + storage[0] = 2.0; + ImageFilter filter2a = ImageFilter.matrix(storage, filterQuality: FilterQuality.none); + ImageFilter filter2b = ImageFilter.matrix(storage, filterQuality: FilterQuality.high); + + expect(filter1a, filter1a); + expect(filter1a, isNot(equals(filter1b))); + expect(filter1a, isNot(equals(filter2a))); + expect(filter1a, isNot(equals(filter2b))); + + expect(filter1b, isNot(equals(filter1a))); + expect(filter1b, filter1b); + expect(filter1b, isNot(equals(filter2a))); + expect(filter1b, isNot(equals(filter2b))); + + expect(filter2a, isNot(equals(filter1a))); + expect(filter2a, isNot(equals(filter1b))); + expect(filter2a, filter2a); + expect(filter2a, isNot(equals(filter2b))); + + expect(filter2b, isNot(equals(filter1a))); + expect(filter2b, isNot(equals(filter1b))); + expect(filter2b, isNot(equals(filter2a))); + expect(filter2b, filter2b); + }); + + test('blur tests all values on ==', () { + ImageFilter filter1 = ImageFilter.blur(sigmaX: 2.0, sigmaY: 2.0, tileMode: TileMode.decal); + ImageFilter filter2 = ImageFilter.blur(sigmaX: 2.0, sigmaY: 3.0, tileMode: TileMode.decal); + ImageFilter filter3 = ImageFilter.blur(sigmaX: 2.0, sigmaY: 2.0, tileMode: TileMode.mirror); + + expect(filter1, filter1); + expect(filter1, isNot(equals(filter2))); + expect(filter1, isNot(equals(filter3))); + + expect(filter2, isNot(equals(filter1))); + expect(filter2, filter2); + expect(filter2, isNot(equals(filter3))); + + expect(filter3, isNot(equals(filter1))); + expect(filter3, isNot(equals(filter2))); + expect(filter3, filter3); + }); + }); +} From 025a3e3f2a2e0462dfa7e8ad89b23f0214173f63 Mon Sep 17 00:00:00 2001 From: Jim Graham Date: Mon, 17 May 2021 13:57:12 -0700 Subject: [PATCH 3/3] adjust to new web library packaging --- lib/web_ui/lib/src/engine/canvaskit/image_filter.dart | 5 ++++- lib/web_ui/lib/src/engine/html/backdrop_filter.dart | 4 ++-- lib/web_ui/lib/src/engine/html/image_filter.dart | 4 ++-- lib/web_ui/lib/src/engine/html/scene_builder.dart | 7 ------- lib/web_ui/lib/src/engine/html/shaders/shader.dart | 10 +++++----- lib/web_ui/lib/src/engine/util.dart | 7 +++++++ 6 files changed, 20 insertions(+), 17 deletions(-) diff --git a/lib/web_ui/lib/src/engine/canvaskit/image_filter.dart b/lib/web_ui/lib/src/engine/canvaskit/image_filter.dart index bdd3f0cfdd083..990360995eb21 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/image_filter.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/image_filter.dart @@ -2,11 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:typed_data'; + import 'package:ui/ui.dart' as ui; import 'canvaskit_api.dart'; import 'color_filter.dart'; import 'skia_object_cache.dart'; +import '../util.dart'; /// An [ImageFilter] that can create a managed skia [SkImageFilter] object. /// @@ -152,7 +155,7 @@ class _CkMatrixImageFilter extends CkImageFilter { return false; return other is _CkMatrixImageFilter && other.filterQuality == filterQuality - && _listEquals(other.matrix, matrix); + && listEquals(other.matrix, matrix); } @override diff --git a/lib/web_ui/lib/src/engine/html/backdrop_filter.dart b/lib/web_ui/lib/src/engine/html/backdrop_filter.dart index 191d6bfc6f8b8..64adaa3319995 100644 --- a/lib/web_ui/lib/src/engine/html/backdrop_filter.dart +++ b/lib/web_ui/lib/src/engine/html/backdrop_filter.dart @@ -113,9 +113,9 @@ class PersistedBackdropFilter extends PersistedContainerSurface // the blur will fall within 2 * sigma pixels. if (browserEngine == BrowserEngine.webkit) { DomRenderer.setElementStyle(_filterElement!, '-webkit-backdrop-filter', - filter._filterAttribute); + filter.filterAttribute); } - DomRenderer.setElementStyle(_filterElement!, 'backdrop-filter', filter._filterAttribute); + DomRenderer.setElementStyle(_filterElement!, 'backdrop-filter', filter.filterAttribute); } } diff --git a/lib/web_ui/lib/src/engine/html/image_filter.dart b/lib/web_ui/lib/src/engine/html/image_filter.dart index 2f2c87c2b2ccb..7c7df2a43d586 100644 --- a/lib/web_ui/lib/src/engine/html/image_filter.dart +++ b/lib/web_ui/lib/src/engine/html/image_filter.dart @@ -18,8 +18,8 @@ class PersistedImageFilter extends PersistedContainerSurface @override void apply() { - rootElement!.style.filter = (filter as EngineImageFilter)._filterAttribute; - rootElement!.style.transform = (filter as EngineImageFilter)._transformAttribute; + rootElement!.style.filter = (filter as EngineImageFilter).filterAttribute; + rootElement!.style.transform = (filter as EngineImageFilter).transformAttribute; } @override diff --git a/lib/web_ui/lib/src/engine/html/scene_builder.dart b/lib/web_ui/lib/src/engine/html/scene_builder.dart index bc87571700eaf..5fe793e5bb98c 100644 --- a/lib/web_ui/lib/src/engine/html/scene_builder.dart +++ b/lib/web_ui/lib/src/engine/html/scene_builder.dart @@ -582,10 +582,3 @@ class SurfaceSceneBuilder implements ui.SceneBuilder { throw UnimplementedError(); } } - -// HTML only supports a single radius, but Flutter ImageFilter supports separate -// horizontal and vertical radii. The best approximation we can provide is to -// average the two radii together for a single compromise value. -String _imageFilterToCss(_BlurEngineImageFilter filter) { - return 'blur(${(filter.sigmaX + filter.sigmaY) / 2}px)'; -} diff --git a/lib/web_ui/lib/src/engine/html/shaders/shader.dart b/lib/web_ui/lib/src/engine/html/shaders/shader.dart index 89886777578c8..c5f374b2621f6 100644 --- a/lib/web_ui/lib/src/engine/html/shaders/shader.dart +++ b/lib/web_ui/lib/src/engine/html/shaders/shader.dart @@ -675,8 +675,8 @@ abstract class EngineImageFilter implements ui.ImageFilter { EngineImageFilter._(); - String get _filterAttribute => ''; - String get _transformAttribute => ''; + String get filterAttribute => ''; + String get transformAttribute => ''; } class _BlurEngineImageFilter extends EngineImageFilter { @@ -687,7 +687,7 @@ class _BlurEngineImageFilter extends EngineImageFilter { final ui.TileMode tileMode; // TODO(flutter_web): implement TileMode. - String get _filterAttribute => _imageFilterToCss(this); + String get filterAttribute => blurSigmasToCssString(sigmaX, sigmaY); @override bool operator ==(Object other) { @@ -717,7 +717,7 @@ class _MatrixEngineImageFilter extends EngineImageFilter { final ui.FilterQuality filterQuality; // TODO(flutter_web): implement FilterQuality. - String get _transformAttribute => float64ListToCssTransform(webMatrix); + String get transformAttribute => float64ListToCssTransform(webMatrix); @override bool operator ==(Object other) { @@ -725,7 +725,7 @@ class _MatrixEngineImageFilter extends EngineImageFilter { return false; return other is _MatrixEngineImageFilter && other.filterQuality == filterQuality - && _listEquals(other.webMatrix, webMatrix); + && listEquals(other.webMatrix, webMatrix); } @override diff --git a/lib/web_ui/lib/src/engine/util.dart b/lib/web_ui/lib/src/engine/util.dart index 8df961341ce36..46b609b145ce5 100644 --- a/lib/web_ui/lib/src/engine/util.dart +++ b/lib/web_ui/lib/src/engine/util.dart @@ -552,3 +552,10 @@ bool listEquals(List? a, List? b) { } return true; } + +// HTML only supports a single radius, but Flutter ImageFilter supports separate +// horizontal and vertical radii. The best approximation we can provide is to +// average the two radii together for a single compromise value. +String blurSigmasToCssString(double sigmaX, double sigmaY) { + return 'blur(${(sigmaX + sigmaY) * 0.5}px)'; +}