Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
weixin_43355755
engine
提交
156c2beb
E
engine
项目概览
weixin_43355755
/
engine
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
E
engine
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
156c2beb
编写于
5月 17, 2021
作者:
J
Jim Graham
提交者:
GitHub
5月 17, 2021
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Web ImageFilter.matrix support (#25982)
上级
62e09512
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
225 addition
and
30 deletion
+225
-30
lib/web_ui/lib/src/engine/canvaskit/image_filter.dart
lib/web_ui/lib/src/engine/canvaskit/image_filter.dart
+39
-1
lib/web_ui/lib/src/engine/html/backdrop_filter.dart
lib/web_ui/lib/src/engine/html/backdrop_filter.dart
+2
-2
lib/web_ui/lib/src/engine/html/image_filter.dart
lib/web_ui/lib/src/engine/html/image_filter.dart
+2
-1
lib/web_ui/lib/src/engine/html/scene_builder.dart
lib/web_ui/lib/src/engine/html/scene_builder.dart
+0
-7
lib/web_ui/lib/src/engine/html/shaders/shader.dart
lib/web_ui/lib/src/engine/html/shaders/shader.dart
+60
-6
lib/web_ui/lib/src/engine/util.dart
lib/web_ui/lib/src/engine/util.dart
+13
-6
lib/web_ui/lib/src/ui/painting.dart
lib/web_ui/lib/src/ui/painting.dart
+10
-6
lib/web_ui/test/engine/surface/filters/image_filter_test.dart
...web_ui/test/engine/surface/filters/image_filter_test.dart
+79
-0
lib/web_ui/test/golden_tests/engine/compositing_golden_test.dart
..._ui/test/golden_tests/engine/compositing_golden_test.dart
+20
-1
未找到文件。
lib/web_ui/lib/src/engine/canvaskit/image_filter.dart
浏览文件 @
156c2beb
...
...
@@ -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.
///
...
...
@@ -22,7 +25,7 @@ abstract class CkManagedSkImageFilterConvertible<T extends Object>
/// The CanvasKit implementation of [ui.ImageFilter].
///
/// Currently only supports `blur`.
/// Currently only supports `blur`
, `matrix`, and ColorFilters
.
abstract
class
CkImageFilter
extends
ManagedSkiaObject
<
SkImageFilter
>
implements
CkManagedSkImageFilterConvertible
<
SkImageFilter
>
{
factory
CkImageFilter
.
blur
(
...
...
@@ -31,6 +34,9 @@ abstract class CkImageFilter extends ManagedSkiaObject<SkImageFilter>
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 +132,35 @@ class _CkBlurImageFilter extends CkImageFilter {
return
'ImageFilter.blur(
$sigmaX
,
$sigmaY
,
$_modeString
)'
;
}
}
class
_CkMatrixImageFilter
extends
CkImageFilter
{
_CkMatrixImageFilter
({
required
Float64List
matrix
,
required
this
.
filterQuality
})
:
this
.
matrix
=
Float64List
.
fromList
(
matrix
),
super
.
_
();
final
Float64List
matrix
;
final
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
<
double
>(
other
.
matrix
,
matrix
);
}
@override
int
get
hashCode
=>
ui
.
hashValues
(
filterQuality
,
ui
.
hashList
(
matrix
));
@override
String
toString
()
=>
'ImageFilter.matrix(
$matrix
,
$filterQuality
)'
;
}
lib/web_ui/lib/src/engine/html/backdrop_filter.dart
浏览文件 @
156c2beb
...
...
@@ -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
);
}
}
...
...
lib/web_ui/lib/src/engine/html/image_filter.dart
浏览文件 @
156c2beb
...
...
@@ -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
...
...
lib/web_ui/lib/src/engine/html/scene_builder.dart
浏览文件 @
156c2beb
...
...
@@ -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
(
EngineImageFilter
filter
)
{
return
'blur(
${(filter.sigmaX + filter.sigmaY) / 2}
px)'
;
}
lib/web_ui/lib/src/engine/html/shaders/shader.dart
浏览文件 @
156c2beb
...
...
@@ -660,25 +660,79 @@ 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
,
required
ui
.
TileMode
tileMode
,
})
=
_BlurEngineImageFilter
;
factory
EngineImageFilter
.
matrix
({
required
Float64List
matrix
,
required
ui
.
FilterQuality
filterQuality
,
})
=
_MatrixEngineImageFilter
;
EngineImageFilter
.
_
();
String
get
filterAttribute
=>
''
;
String
get
transformAttribute
=>
''
;
}
class
_BlurEngineImageFilter
extends
EngineImageFilter
{
_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
=>
blurSigmasToCssString
(
sigmaX
,
sigmaY
);
@override
bool
operator
==(
Object
other
)
{
return
other
is
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
,
$tileMode
)'
;
}
}
class
_MatrixEngineImageFilter
extends
EngineImageFilter
{
_MatrixEngineImageFilter
({
required
Float64List
matrix
,
required
this
.
filterQuality
})
:
webMatrix
=
Float64List
.
fromList
(
matrix
),
super
.
_
();
final
Float64List
webMatrix
;
final
ui
.
FilterQuality
filterQuality
;
// 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
<
double
>(
other
.
webMatrix
,
webMatrix
);
}
@override
int
get
hashCode
=>
ui
.
hashValues
(
ui
.
hashList
(
webMatrix
),
filterQuality
);
@override
String
toString
()
{
return
'ImageFilter.
blur(
$sigmaX
,
$sigmaY
)'
;
return
'ImageFilter.
matrix(
$webMatrix
,
$filterQuality
)'
;
}
}
lib/web_ui/lib/src/engine/util.dart
浏览文件 @
156c2beb
...
...
@@ -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
<
double
>
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
<
double
>
matrix
)
{
assert
(
matrix
.
length
==
16
);
final
Float32List
m
=
matrix
;
final
List
<
double
>
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
<
double
>
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
<
double
>
matrix
)
{
assert
(
matrix
.
length
==
16
);
final
Float32List
m
=
matrix
;
final
List
<
double
>
m
=
matrix
;
if
(
m
[
0
]
==
1.0
&&
m
[
1
]
==
0.0
&&
m
[
2
]
==
0.0
&&
...
...
@@ -552,3 +552,10 @@ bool listEquals<T>(List<T>? a, List<T>? 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)'
;
}
lib/web_ui/lib/src/ui/painting.dart
浏览文件 @
156c2beb
...
...
@@ -399,14 +399,18 @@ class ImageFilter {
if
(
engine
.
useCanvasKit
)
{
return
engine
.
CkImageFilter
.
blur
(
sigmaX:
sigmaX
,
sigmaY:
sigmaY
,
tileMode:
tileMode
);
}
return
engine
.
EngineImageFilter
.
blur
(
sigmaX:
sigmaX
,
sigmaY:
sigmaY
);
// TODO(flutter_web): implement TileMode.
return
engine
.
EngineImageFilter
.
blur
(
sigmaX:
sigmaX
,
sigmaY:
sigmaY
,
tileMode:
tileMode
);
}
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
,
filterQuality:
filterQuality
);
}
ImageFilter
.
compose
({
required
ImageFilter
outer
,
required
ImageFilter
inner
})
{
...
...
lib/web_ui/test/engine/surface/filters/image_filter_test.dart
0 → 100644
浏览文件 @
156c2beb
// 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
);
});
});
}
lib/web_ui/test/golden_tests/engine/compositing_golden_test.dart
浏览文件 @
156c2beb
...
...
@@ -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
();
});
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录