Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
weixin_43355755
engine
提交
6e15044e
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,发现更多精彩内容 >>
未验证
提交
6e15044e
编写于
11月 10, 2020
作者:
F
Ferhat
提交者:
GitHub
11月 10, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[web] Speed up PageView/CustomPainter rendering (#22408)
上级
aeab315d
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
139 addition
and
41 deletion
+139
-41
lib/web_ui/lib/src/engine/bitmap_canvas.dart
lib/web_ui/lib/src/engine/bitmap_canvas.dart
+25
-10
lib/web_ui/lib/src/engine/html/clip.dart
lib/web_ui/lib/src/engine/html/clip.dart
+5
-5
lib/web_ui/lib/src/engine/html/path/path.dart
lib/web_ui/lib/src/engine/html/path/path.dart
+21
-7
lib/web_ui/lib/src/engine/html/path/path_ref.dart
lib/web_ui/lib/src/engine/html/path/path_ref.dart
+53
-4
lib/web_ui/lib/src/engine/html/recording_canvas.dart
lib/web_ui/lib/src/engine/html/recording_canvas.dart
+2
-2
lib/web_ui/test/path_test.dart
lib/web_ui/test/path_test.dart
+33
-13
未找到文件。
lib/web_ui/lib/src/engine/bitmap_canvas.dart
浏览文件 @
6e15044e
...
...
@@ -331,17 +331,12 @@ class BitmapCanvas extends EngineCanvas {
/// - Pictures typically have large rect/rounded rectangles as background
/// prefer DOM if canvas has not been allocated yet.
///
/// Future optimization: The check below can be used to prevent excessive
/// canvas sandwiching (switching between dom and multiple canvas(s)).
/// Once RecordingCanvas is updated to detect switch count, this can be
/// enabled.
/// (_canvasPool._canvas == null &&
/// paint.maskFilter == null &&
/// paint.shader == null &&
/// paint.style != ui.PaintingStyle.stroke)
///
bool
_useDomForRendering
(
SurfacePaintData
paint
)
=>
_preserveImageData
==
false
&&
_contains3dTransform
;
(
_preserveImageData
==
false
&&
_contains3dTransform
)
||
(
_childOverdraw
&&
_canvasPool
.
_canvas
==
null
&&
paint
.
maskFilter
==
null
&&
paint
.
shader
==
null
&&
paint
.
style
!=
ui
.
PaintingStyle
.
stroke
);
@override
void
drawColor
(
ui
.
Color
color
,
ui
.
BlendMode
blendMode
)
{
...
...
@@ -495,6 +490,26 @@ class BitmapCanvas extends EngineCanvas {
if
(
_useDomForRendering
(
paint
))
{
final
Matrix4
transform
=
_canvasPool
.
_currentTransform
;
final
SurfacePath
surfacePath
=
path
as
SurfacePath
;
final
ui
.
Rect
?
pathAsLine
=
surfacePath
.
toStraightLine
();
if
(
pathAsLine
!=
null
)
{
final
ui
.
Rect
rect
=
(
pathAsLine
.
top
==
pathAsLine
.
bottom
)
?
ui
.
Rect
.
fromLTWH
(
pathAsLine
.
left
,
pathAsLine
.
top
,
pathAsLine
.
width
,
1
)
:
ui
.
Rect
.
fromLTWH
(
pathAsLine
.
left
,
pathAsLine
.
top
,
1
,
pathAsLine
.
height
);
html
.
HtmlElement
element
=
_buildDrawRectElement
(
rect
,
paint
,
'draw-rect'
,
_canvasPool
.
_currentTransform
);
_drawElement
(
element
,
ui
.
Offset
(
math
.
min
(
rect
.
left
,
rect
.
right
),
math
.
min
(
rect
.
top
,
rect
.
bottom
)),
paint
);
return
;
}
final
ui
.
Rect
?
pathAsRect
=
surfacePath
.
toRect
();
if
(
pathAsRect
!=
null
)
{
drawRect
(
pathAsRect
,
paint
);
return
;
}
final
ui
.
Rect
pathBounds
=
surfacePath
.
getBounds
();
html
.
Element
svgElm
=
_pathToSvgElement
(
surfacePath
,
paint
,
'
${pathBounds.right}
'
,
'
${pathBounds.bottom}
'
);
...
...
lib/web_ui/lib/src/engine/html/clip.dart
浏览文件 @
6e15044e
...
...
@@ -195,11 +195,11 @@ class PersistedPhysicalShape extends PersistedContainerSurface
void
recomputeTransformAndClip
()
{
_transform
=
parent
!.
_transform
;
final
ui
.
RRect
?
roundRect
=
path
.
webOnlyPathAsRoundedRect
;
final
ui
.
RRect
?
roundRect
=
path
.
toRoundedRect
()
;
if
(
roundRect
!=
null
)
{
_localClipBounds
=
roundRect
.
outerRect
;
}
else
{
final
ui
.
Rect
?
rect
=
path
.
webOnlyPathAsRect
;
final
ui
.
Rect
?
rect
=
path
.
toRect
()
;
if
(
rect
!=
null
)
{
_localClipBounds
=
rect
;
}
else
{
...
...
@@ -233,7 +233,7 @@ class PersistedPhysicalShape extends PersistedContainerSurface
void
_applyShape
()
{
// Handle special case of round rect physical shape mapping to
// rounded div.
final
ui
.
RRect
?
roundRect
=
path
.
webOnlyPathAsRoundedRect
;
final
ui
.
RRect
?
roundRect
=
path
.
toRoundedRect
()
;
if
(
roundRect
!=
null
)
{
final
String
borderRadius
=
'
${roundRect.tlRadiusX}
px
${roundRect.trRadiusX}
px '
...
...
@@ -253,7 +253,7 @@ class PersistedPhysicalShape extends PersistedContainerSurface
}
return
;
}
else
{
final
ui
.
Rect
?
rect
=
path
.
webOnlyPathAsRect
;
final
ui
.
Rect
?
rect
=
path
.
toRect
()
;
if
(
rect
!=
null
)
{
final
html
.
CssStyleDeclaration
style
=
rootElement
!.
style
;
style
...
...
@@ -270,7 +270,7 @@ class PersistedPhysicalShape extends PersistedContainerSurface
}
return
;
}
else
{
final
ui
.
Rect
?
ovalRect
=
path
.
webOnlyPathAsCircle
;
final
ui
.
Rect
?
ovalRect
=
path
.
toCircle
()
;
if
(
ovalRect
!=
null
)
{
final
double
rx
=
ovalRect
.
width
/
2.0
;
final
double
ry
=
ovalRect
.
height
/
2.0
;
...
...
lib/web_ui/lib/src/engine/html/path/path.dart
浏览文件 @
6e15044e
...
...
@@ -1524,24 +1524,38 @@ class SurfacePath implements ui.Path {
return
SurfacePathMetrics
.
_
(
this
,
forceClosed
);
}
/// Detects if path is rounded rectangle and returns rounded rectangle or
/// null.
/// Detects if path is rounded rectangle.
///
/// Returns rounded rectangle or null.
///
/// Used for web optimization of physical shape represented as
/// a persistent div.
ui
.
RRect
?
get
webOnlyPathAsRoundedRect
=>
pathRef
.
getRRect
();
ui
.
RRect
?
toRoundedRect
()
=>
pathRef
.
getRRect
();
/// Detects if path is simple rectangle and returns rectangle or null.
/// Detects if path is simple rectangle.
///
/// Returns rectangle or null.
///
/// Used for web optimization of physical shape represented as
/// a persistent div. !Warning it does not detect if closed, don't use this
/// for optimizing strokes.
ui
.
Rect
?
toRect
()
=>
pathRef
.
getRect
();
/// Detects if path is a vertical or horizontal line.
///
/// Returns LTRB or null.
///
/// Used for web optimization of physical shape represented as
/// a persistent div.
ui
.
Rect
?
get
webOnlyPathAsRect
=>
pathRef
.
getRect
();
ui
.
Rect
?
toStraightLine
()
=>
pathRef
.
getStraightLine
();
/// Detects if path is simple oval and returns bounding rectangle or null.
/// Detects if path is simple oval.
///
/// Returns bounding rectangle or null.
///
/// Used for web optimization of physical shape represented as
/// a persistent div.
ui
.
Rect
?
get
webOnlyPathAsCircle
=>
ui
.
Rect
?
toCircle
()
=>
pathRef
.
isOval
==
-
1
?
null
:
pathRef
.
getBounds
();
/// Returns if Path is empty.
...
...
lib/web_ui/lib/src/engine/html/path/path_ref.dart
浏览文件 @
6e15044e
...
...
@@ -156,7 +156,16 @@ class PathRef {
int
get
isRRect
=>
fIsRRect
?
fRRectOrOvalStartIdx
:
-
1
;
int
get
isRect
=>
fIsRect
?
fRRectOrOvalStartIdx
:
-
1
;
ui
.
RRect
?
getRRect
()
=>
fIsRRect
?
_getRRect
()
:
null
;
ui
.
Rect
?
getRect
()
=>
fIsRect
?
_getRect
()
:
null
;
ui
.
Rect
?
getRect
()
{
/// Use _detectRect() for detection if explicity addRect was used (fIsRect) or
/// it is a potential due to moveTo + 3 lineTo verbs.
if
(
fIsRect
)
{
return
ui
.
Rect
.
fromLTRB
(
atPoint
(
0
).
dx
,
atPoint
(
0
).
dy
,
atPoint
(
1
).
dx
,
atPoint
(
2
).
dy
);
}
else
{
return
_fVerbsLength
==
4
?
_detectRect
()
:
null
;
}
}
bool
get
isRectCCW
=>
fRRectOrOvalIsCCW
;
bool
get
hasComputedBounds
=>
!
fBoundsIsDirty
;
...
...
@@ -173,9 +182,49 @@ class PathRef {
}
/// Reconstructs Rect from path commands.
ui
.
Rect
_getRect
()
{
return
ui
.
Rect
.
fromLTRB
(
atPoint
(
0
).
dx
,
atPoint
(
0
).
dy
,
atPoint
(
1
).
dx
,
atPoint
(
2
).
dy
);
///
/// Detects clockwise starting with horizontal line.
ui
.
Rect
?
_detectRect
()
{
assert
(
_fVerbs
[
0
]
==
SPath
.
kMoveVerb
);
final
double
x0
=
atPoint
(
0
).
dx
;
final
double
y0
=
atPoint
(
0
).
dy
;
final
double
x1
=
atPoint
(
1
).
dx
;
final
double
y1
=
atPoint
(
1
).
dy
;
if
(
_fVerbs
[
1
]
!=
SPath
.
kLineVerb
||
y1
!=
y0
)
{
return
null
;
}
final
double
width
=
x1
-
x0
;
final
double
x2
=
atPoint
(
2
).
dx
;
final
double
y2
=
atPoint
(
2
).
dy
;
if
(
_fVerbs
[
2
]
!=
SPath
.
kLineVerb
||
x2
!=
x1
)
{
return
null
;
}
final
double
height
=
y2
-
y1
;
final
double
x3
=
atPoint
(
3
).
dx
;
final
double
y3
=
atPoint
(
3
).
dy
;
if
(
_fVerbs
[
3
]
!=
SPath
.
kLineVerb
||
y3
!=
y2
)
{
return
null
;
}
if
((
x2
-
x3
)
!=
width
||
(
y3
-
y0
)
!=
height
)
{
return
null
;
}
return
ui
.
Rect
.
fromLTWH
(
x0
,
y0
,
width
,
height
);
}
/// Returns horizontal/vertical line bounds or null if not a line.
ui
.
Rect
?
getStraightLine
()
{
if
(
_fVerbsLength
!=
2
||
_fVerbs
[
0
]
!=
SPath
.
kMoveVerb
||
_fVerbs
[
1
]
!=
SPath
.
kLineVerb
)
{
return
null
;
}
final
double
x0
=
_fPoints
[
0
];
final
double
y0
=
_fPoints
[
1
];
final
double
x1
=
_fPoints
[
2
];
final
double
y1
=
_fPoints
[
3
];
if
(
y0
==
y1
||
x0
==
x1
)
{
return
ui
.
Rect
.
fromLTRB
(
x0
,
y0
,
x1
,
y1
);
}
return
null
;
}
/// Reconstructs RRect from path commands.
...
...
lib/web_ui/lib/src/engine/html/recording_canvas.dart
浏览文件 @
6e15044e
...
...
@@ -466,12 +466,12 @@ class RecordingCanvas {
// For Rect/RoundedRect paths use drawRect/drawRRect code paths for
// DomCanvas optimization.
SurfacePath
sPath
=
path
as
SurfacePath
;
final
ui
.
Rect
?
rect
=
sPath
.
webOnlyPathAsRect
;
final
ui
.
Rect
?
rect
=
sPath
.
toRect
()
;
if
(
rect
!=
null
)
{
drawRect
(
rect
,
paint
);
return
;
}
final
ui
.
RRect
?
rrect
=
sPath
.
webOnlyPathAsRoundedRect
;
final
ui
.
RRect
?
rrect
=
sPath
.
toRoundedRect
()
;
if
(
rrect
!=
null
)
{
drawRRect
(
rrect
,
paint
);
return
;
...
...
lib/web_ui/test/path_test.dart
浏览文件 @
6e15044e
...
...
@@ -83,12 +83,32 @@ void testMain() {
test
(
'Should detect rectangular path'
,
()
{
final
SurfacePath
path
=
SurfacePath
();
path
.
addRect
(
const
Rect
.
fromLTWH
(
1.0
,
2.0
,
3.0
,
4.0
));
expect
(
path
.
webOnlyPathAsRect
,
const
Rect
.
fromLTWH
(
1.0
,
2.0
,
3.0
,
4.0
));
expect
(
path
.
toRect
(),
const
Rect
.
fromLTWH
(
1.0
,
2.0
,
3.0
,
4.0
));
});
test
(
'Should detect horizontal line path'
,
()
{
SurfacePath
path
=
SurfacePath
();
path
.
moveTo
(
10
,
20
);
path
.
lineTo
(
100
,
0
);
expect
(
path
.
toStraightLine
(),
null
);
path
=
SurfacePath
();
path
.
moveTo
(
10
,
20
);
path
.
lineTo
(
200
,
20
);
Rect
r
=
path
.
toStraightLine
()!;
expect
(
r
,
equals
(
Rect
.
fromLTRB
(
10
,
20
,
200
,
20
)));
});
test
(
'Should detect vertical line path'
,
()
{
final
SurfacePath
path
=
SurfacePath
();
path
.
moveTo
(
10
,
20
);
path
.
lineTo
(
10
,
200
);
Rect
r
=
path
.
toStraightLine
()!;
expect
(
r
,
equals
(
Rect
.
fromLTRB
(
10
,
20
,
10
,
200
)));
});
test
(
'Should detect non rectangular path if empty'
,
()
{
final
SurfacePath
path
=
SurfacePath
();
expect
(
path
.
webOnlyPathAsRect
,
null
);
expect
(
path
.
toRect
()
,
null
);
});
test
(
'Should detect non rectangular path if there are multiple subpaths'
,
...
...
@@ -96,7 +116,7 @@ void testMain() {
final
SurfacePath
path
=
SurfacePath
();
path
.
addRect
(
const
Rect
.
fromLTWH
(
1.0
,
2.0
,
3.0
,
4.0
));
path
.
addRect
(
const
Rect
.
fromLTWH
(
5.0
,
6.0
,
7.0
,
8.0
));
expect
(
path
.
webOnlyPathAsRect
,
null
);
expect
(
path
.
toRect
()
,
null
);
});
test
(
'Should detect rounded rectangular path'
,
()
{
...
...
@@ -105,20 +125,20 @@ void testMain() {
const
Rect
.
fromLTRB
(
1.0
,
2.0
,
30.0
,
40.0
),
const
Radius
.
circular
(
2.0
)));
expect
(
path
.
webOnlyPathAsRoundedRect
,
path
.
toRoundedRect
()
,
RRect
.
fromRectAndRadius
(
const
Rect
.
fromLTRB
(
1.0
,
2.0
,
30.0
,
40.0
),
const
Radius
.
circular
(
2.0
)));
});
test
(
'Should detect non rounded rectangular path if empty'
,
()
{
final
SurfacePath
path
=
SurfacePath
();
expect
(
path
.
webOnlyPathAsRoundedRect
,
null
);
expect
(
path
.
toRoundedRect
()
,
null
);
});
test
(
'Should detect rectangular path is not round'
,
()
{
final
SurfacePath
path
=
SurfacePath
();
path
.
addRect
(
const
Rect
.
fromLTWH
(
1.0
,
2.0
,
3.0
,
4.0
));
expect
(
path
.
webOnlyPathAsRoundedRect
,
null
);
expect
(
path
.
toRoundedRect
()
,
null
);
});
test
(
...
...
@@ -129,7 +149,7 @@ void testMain() {
const
Rect
.
fromLTWH
(
1.0
,
2.0
,
3.0
,
4.0
),
const
Radius
.
circular
(
2.0
)));
path
.
addRRect
(
RRect
.
fromRectAndRadius
(
const
Rect
.
fromLTWH
(
1.0
,
2.0
,
3.0
,
4.0
),
const
Radius
.
circular
(
2.0
)));
expect
(
path
.
webOnlyPathAsRoundedRect
,
null
);
expect
(
path
.
toRoundedRect
()
,
null
);
});
test
(
'Should compute bounds as empty for empty and moveTo only path'
,
()
{
...
...
@@ -161,7 +181,7 @@ void testMain() {
bottomRight:
Radius
.
elliptical
(
7
,
8
));
path
.
addRRect
(
rrect
);
expect
(
path
.
getBounds
(),
bounds
);
expect
(
path
.
webOnlyPathAsRoundedRect
,
rrect
);
expect
(
path
.
toRoundedRect
()
,
rrect
);
path
=
SurfacePath
();
rrect
=
RRect
.
fromRectAndCorners
(
bounds
,
topLeft:
Radius
.
elliptical
(
0
,
2
),
...
...
@@ -170,7 +190,7 @@ void testMain() {
bottomRight:
Radius
.
elliptical
(
7
,
8
));
path
.
addRRect
(
rrect
);
expect
(
path
.
getBounds
(),
bounds
);
expect
(
path
.
webOnlyPathAsRoundedRect
,
rrect
);
expect
(
path
.
toRoundedRect
()
,
rrect
);
path
=
SurfacePath
();
rrect
=
RRect
.
fromRectAndCorners
(
bounds
,
topLeft:
Radius
.
elliptical
(
0
,
0
),
...
...
@@ -179,7 +199,7 @@ void testMain() {
bottomRight:
Radius
.
elliptical
(
7
,
8
));
path
.
addRRect
(
rrect
);
expect
(
path
.
getBounds
(),
bounds
);
expect
(
path
.
webOnlyPathAsRoundedRect
,
rrect
);
expect
(
path
.
toRoundedRect
()
,
rrect
);
path
=
SurfacePath
();
rrect
=
RRect
.
fromRectAndCorners
(
bounds
,
topLeft:
Radius
.
elliptical
(
1
,
2
),
...
...
@@ -188,7 +208,7 @@ void testMain() {
bottomRight:
Radius
.
elliptical
(
7
,
8
));
path
.
addRRect
(
rrect
);
expect
(
path
.
getBounds
(),
bounds
);
expect
(
path
.
webOnlyPathAsRoundedRect
,
rrect
);
expect
(
path
.
toRoundedRect
()
,
rrect
);
path
=
SurfacePath
();
rrect
=
RRect
.
fromRectAndCorners
(
bounds
,
topLeft:
Radius
.
elliptical
(
1
,
2
),
...
...
@@ -197,7 +217,7 @@ void testMain() {
bottomRight:
Radius
.
elliptical
(
7
,
8
));
path
.
addRRect
(
rrect
);
expect
(
path
.
getBounds
(),
bounds
);
expect
(
path
.
webOnlyPathAsRoundedRect
,
rrect
);
expect
(
path
.
toRoundedRect
()
,
rrect
);
path
=
SurfacePath
();
rrect
=
RRect
.
fromRectAndCorners
(
bounds
,
topLeft:
Radius
.
elliptical
(
1
,
2
),
...
...
@@ -206,7 +226,7 @@ void testMain() {
bottomRight:
Radius
.
elliptical
(
0
,
0
));
path
.
addRRect
(
rrect
);
expect
(
path
.
getBounds
(),
bounds
);
expect
(
path
.
webOnlyPathAsRoundedRect
,
rrect
);
expect
(
path
.
toRoundedRect
()
,
rrect
);
});
test
(
'Should compute bounds for lines'
,
()
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录