Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
liujiuri
engine
提交
e763e567
E
engine
项目概览
liujiuri
/
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,体验更适合开发者的 AI 搜索 >>
未验证
提交
e763e567
编写于
3月 01, 2021
作者:
Y
Yegor
提交者:
GitHub
3月 01, 2021
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
remove _getRRect: fixes assertion error (#24688)
上级
17f6bfc4
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
154 addition
and
106 deletion
+154
-106
lib/web_ui/lib/src/engine/html/path/path.dart
lib/web_ui/lib/src/engine/html/path/path.dart
+60
-22
lib/web_ui/lib/src/engine/html/path/path_ref.dart
lib/web_ui/lib/src/engine/html/path/path_ref.dart
+21
-84
lib/web_ui/test/engine/surface/path/path_ref_test.dart
lib/web_ui/test/engine/surface/path/path_ref_test.dart
+73
-0
未找到文件。
lib/web_ui/lib/src/engine/html/path/path.dart
浏览文件 @
e763e567
...
...
@@ -1007,42 +1007,80 @@ class SurfacePath implements ui.Path {
_addOval
(
bounds
,
direction
,
startIndex
~/
2
);
}
else
{
final
double
weight
=
SPath
.
scalarRoot2Over2
;
double
left
=
bounds
.
left
;
double
right
=
bounds
.
right
;
double
top
=
bounds
.
top
;
double
bottom
=
bounds
.
bottom
;
final
double
left
=
bounds
.
left
;
final
double
right
=
bounds
.
right
;
final
double
top
=
bounds
.
top
;
final
double
bottom
=
bounds
.
bottom
;
final
double
width
=
right
-
left
;
final
double
height
=
bottom
-
top
;
// Proportionally scale down all radii to fit. Find the minimum ratio
// of a side and the radii on that side (for all four sides) and use
// that to scale down _all_ the radii. This algorithm is from the
// W3 spec (http://www.w3.org/TR/css3-background/) section 5.5
final
double
tlRadiusX
=
math
.
max
(
0
,
rrect
.
tlRadiusX
);
final
double
trRadiusX
=
math
.
max
(
0
,
rrect
.
trRadiusX
);
final
double
blRadiusX
=
math
.
max
(
0
,
rrect
.
blRadiusX
);
final
double
brRadiusX
=
math
.
max
(
0
,
rrect
.
brRadiusX
);
final
double
tlRadiusY
=
math
.
max
(
0
,
rrect
.
tlRadiusY
);
final
double
trRadiusY
=
math
.
max
(
0
,
rrect
.
trRadiusY
);
final
double
blRadiusY
=
math
.
max
(
0
,
rrect
.
blRadiusY
);
final
double
brRadiusY
=
math
.
max
(
0
,
rrect
.
brRadiusY
);
double
tlRadiusX
=
math
.
max
(
0
,
rrect
.
tlRadiusX
);
double
trRadiusX
=
math
.
max
(
0
,
rrect
.
trRadiusX
);
double
blRadiusX
=
math
.
max
(
0
,
rrect
.
blRadiusX
);
double
brRadiusX
=
math
.
max
(
0
,
rrect
.
brRadiusX
);
double
tlRadiusY
=
math
.
max
(
0
,
rrect
.
tlRadiusY
);
double
trRadiusY
=
math
.
max
(
0
,
rrect
.
trRadiusY
);
double
blRadiusY
=
math
.
max
(
0
,
rrect
.
blRadiusY
);
double
brRadiusY
=
math
.
max
(
0
,
rrect
.
brRadiusY
);
double
scale
=
_computeMinScale
(
tlRadiusX
,
trRadiusX
,
width
,
1.0
);
scale
=
_computeMinScale
(
blRadiusX
,
brRadiusX
,
width
,
scale
);
scale
=
_computeMinScale
(
tlRadiusY
,
trRadiusY
,
height
,
scale
);
scale
=
_computeMinScale
(
blRadiusY
,
brRadiusY
,
height
,
scale
);
// Inlined version of:
moveTo
(
left
,
bottom
-
scale
*
blRadiusY
);
lineTo
(
left
,
top
+
scale
*
tlRadiusY
);
conicTo
(
left
,
top
,
left
+
scale
*
tlRadiusX
,
top
,
weight
);
lineTo
(
right
-
scale
*
trRadiusX
,
top
);
conicTo
(
right
,
top
,
right
,
top
+
scale
*
trRadiusY
,
weight
);
lineTo
(
right
,
bottom
-
scale
*
brRadiusY
);
conicTo
(
right
,
bottom
,
right
-
scale
*
brRadiusX
,
bottom
,
weight
);
lineTo
(
left
+
scale
*
blRadiusX
,
bottom
);
conicTo
(
left
,
bottom
,
left
,
bottom
-
scale
*
blRadiusY
,
weight
);
if
(
scale
!=
1.0
)
{
tlRadiusX
=
scale
*
tlRadiusX
;
trRadiusX
=
scale
*
trRadiusX
;
blRadiusX
=
scale
*
blRadiusX
;
brRadiusX
=
scale
*
brRadiusX
;
tlRadiusY
=
scale
*
tlRadiusY
;
trRadiusY
=
scale
*
trRadiusY
;
blRadiusY
=
scale
*
blRadiusY
;
brRadiusY
=
scale
*
brRadiusY
;
}
// Whether we had to alter the rrect parameters for correctness.
final
bool
isRRectCorrected
=
tlRadiusX
!=
rrect
.
tlRadiusX
||
trRadiusX
!=
rrect
.
trRadiusX
||
blRadiusX
!=
rrect
.
blRadiusX
||
brRadiusX
!=
rrect
.
brRadiusX
||
tlRadiusY
!=
rrect
.
tlRadiusY
||
trRadiusY
!=
rrect
.
trRadiusY
||
blRadiusY
!=
rrect
.
blRadiusY
||
brRadiusY
!=
rrect
.
brRadiusY
;
// Expand the rrect into a series of path ops.
moveTo
(
left
,
bottom
-
blRadiusY
);
lineTo
(
left
,
top
+
tlRadiusY
);
conicTo
(
left
,
top
,
left
+
tlRadiusX
,
top
,
weight
);
lineTo
(
right
-
trRadiusX
,
top
);
conicTo
(
right
,
top
,
right
,
top
+
trRadiusY
,
weight
);
lineTo
(
right
,
bottom
-
brRadiusY
);
conicTo
(
right
,
bottom
,
right
-
brRadiusX
,
bottom
,
weight
);
lineTo
(
left
+
blRadiusX
,
bottom
);
conicTo
(
left
,
bottom
,
left
,
bottom
-
blRadiusY
,
weight
);
close
();
// SkAutoDisableDirectionCheck.
_firstDirection
=
isRRect
?
direction
:
SPathDirection
.
kUnknown
;
// No need to duplicate the rrect if we know the path is not made of a
// single rrect, or if the original rrect was consistent and didn't have
// to be corrected.
if
(
isRRect
&&
isRRectCorrected
)
{
rrect
=
ui
.
RRect
.
fromLTRBAndCorners
(
left
,
top
,
right
,
bottom
,
topLeft:
ui
.
Radius
.
elliptical
(
tlRadiusX
,
tlRadiusY
),
topRight:
ui
.
Radius
.
elliptical
(
trRadiusX
,
trRadiusY
),
bottomLeft:
ui
.
Radius
.
elliptical
(
blRadiusX
,
blRadiusY
),
bottomRight:
ui
.
Radius
.
elliptical
(
brRadiusX
,
brRadiusY
),
);
}
pathRef
.
setIsRRect
(
isRRect
,
direction
==
SPathDirection
.
kCCW
,
startIndex
%
8
,
rrect
);
}
...
...
lib/web_ui/lib/src/engine/html/path/path_ref.dart
浏览文件 @
e763e567
...
...
@@ -61,9 +61,9 @@ class PathRef {
fBoundsIsDirty
=
true
;
// this also invalidates fIsFinite
fSegmentMask
=
0
;
fIsOval
=
false
;
fIsRRect
=
false
;
rrectRepresentation
=
null
;
fIsRect
=
false
;
// The next two values don't matter unless fIsOval
or fIsRRect are true
.
// The next two values don't matter unless fIsOval
is true or rrectRepresentation is not null
.
fRRectOrOvalIsCCW
=
false
;
fRRectOrOvalStartIdx
=
0xAC
;
assert
(()
{
...
...
@@ -104,7 +104,7 @@ class PathRef {
}
fSegmentMask
=
ref
.
fSegmentMask
;
fIsOval
=
ref
.
fIsOval
;
fIsRRect
=
ref
.
fIsRRect
;
rrectRepresentation
=
ref
.
rrectRepresentation
;
fIsRect
=
ref
.
fIsRect
;
fRRectOrOvalIsCCW
=
ref
.
fRRectOrOvalIsCCW
;
fRRectOrOvalStartIdx
=
ref
.
fRRectOrOvalStartIdx
;
...
...
@@ -153,9 +153,9 @@ class PathRef {
int
get
isOval
=>
fIsOval
?
fRRectOrOvalStartIdx
:
-
1
;
bool
get
isOvalCCW
=>
fRRectOrOvalIsCCW
;
int
get
isRRect
=>
fIsRRect
?
fRRectOrOvalStartIdx
:
-
1
;
int
get
isRRect
=>
rrectRepresentation
!=
null
?
fRRectOrOvalStartIdx
:
-
1
;
int
get
isRect
=>
fIsRect
?
fRRectOrOvalStartIdx
:
-
1
;
ui
.
RRect
?
getRRect
()
=>
fIsRRect
?
_getRRect
()
:
null
;
ui
.
RRect
?
getRRect
()
=>
rrectRepresentation
;
ui
.
Rect
?
getRect
()
{
/// Use _detectRect() for detection if explicity addRect was used (fIsRect) or
/// it is a potential due to moveTo + 3 lineTo verbs.
...
...
@@ -227,70 +227,6 @@ class PathRef {
return
null
;
}
/// Reconstructs RRect from path commands.
///
/// Expect 4 Conics and lines between.
/// Use conic points to calculate corner radius.
ui
.
RRect
_getRRect
()
{
ui
.
Rect
bounds
=
getBounds
();
// Radii x,y of 4 corners
final
List
<
ui
.
Radius
>
radii
=
<
ui
.
Radius
>[];
final
PathRefIterator
iter
=
PathRefIterator
(
this
);
final
Float32List
pts
=
Float32List
(
PathRefIterator
.
kMaxBufferSize
);
int
verb
=
iter
.
next
(
pts
);
assert
(
SPath
.
kMoveVerb
==
verb
);
int
cornerIndex
=
0
;
while
((
verb
=
iter
.
next
(
pts
))
!=
SPath
.
kDoneVerb
)
{
if
(
SPath
.
kConicVerb
==
verb
)
{
final
double
controlPx
=
pts
[
2
];
final
double
controlPy
=
pts
[
3
];
double
vector1_0x
=
controlPx
-
pts
[
0
];
double
vector1_0y
=
controlPy
-
pts
[
1
];
double
vector2_1x
=
pts
[
4
]
-
pts
[
2
];
double
vector2_1y
=
pts
[
5
]
-
pts
[
3
];
double
dx
,
dy
;
// Depending on the corner we have control point at same
// horizontal position as startpoint or same vertical position.
// The location delta of control point specifies corner radius.
if
(
vector1_0x
!=
0.0
)
{
// For CW : Top right or bottom left corners.
assert
(
vector2_1x
==
0.0
&&
vector1_0y
==
0.0
);
dx
=
vector1_0x
.
abs
();
dy
=
vector2_1y
.
abs
();
}
else
if
(
vector1_0y
!=
0.0
)
{
assert
(
vector2_1x
==
0.0
||
vector2_1y
==
0.0
);
dx
=
vector2_1x
.
abs
();
dy
=
vector1_0y
.
abs
();
}
else
{
assert
(
vector2_1y
==
0.0
);
dx
=
vector1_0x
.
abs
();
dy
=
vector1_0y
.
abs
();
}
if
(
assertionsEnabled
)
{
final
int
checkCornerIndex
=
_nearlyEqual
(
controlPx
,
bounds
.
left
)
?
(
_nearlyEqual
(
controlPy
,
bounds
.
top
)
?
_Corner
.
kUpperLeft
:
_Corner
.
kLowerLeft
)
:
(
_nearlyEqual
(
controlPy
,
bounds
.
top
)
?
_Corner
.
kUpperRight
:
_Corner
.
kLowerRight
);
assert
(
checkCornerIndex
==
cornerIndex
);
}
radii
.
add
(
ui
.
Radius
.
elliptical
(
dx
,
dy
));
++
cornerIndex
;
}
else
{
assert
((
verb
==
SPath
.
kLineVerb
&&
((
pts
[
2
]
-
pts
[
0
])
==
0
||
(
pts
[
3
]
-
pts
[
1
])
==
0
))
||
verb
==
SPath
.
kCloseVerb
);
}
}
return
ui
.
RRect
.
fromRectAndCorners
(
bounds
,
topLeft:
radii
[
_Corner
.
kUpperLeft
],
topRight:
radii
[
_Corner
.
kUpperRight
],
bottomRight:
radii
[
_Corner
.
kLowerRight
],
bottomLeft:
radii
[
_Corner
.
kLowerLeft
]);
}
bool
operator
==(
Object
other
)
{
if
(
identical
(
this
,
other
))
{
return
true
;
...
...
@@ -394,7 +330,7 @@ class PathRef {
}
fSegmentMask
=
source
.
fSegmentMask
;
fIsOval
=
source
.
fIsOval
;
fIsRRect
=
source
.
fIsRRect
;
rrectRepresentation
=
source
.
rrectRepresentation
;
fIsRect
=
source
.
fIsRect
;
fRRectOrOvalIsCCW
=
source
.
fRRectOrOvalIsCCW
;
fRRectOrOvalStartIdx
=
source
.
fRRectOrOvalStartIdx
;
...
...
@@ -427,7 +363,7 @@ class PathRef {
}
fSegmentMask
=
ref
.
fSegmentMask
;
fIsOval
=
ref
.
fIsOval
;
fIsRRect
=
ref
.
fIsRRect
;
rrectRepresentation
=
ref
.
rrectRepresentation
;
fIsRect
=
ref
.
fIsRect
;
fRRectOrOvalIsCCW
=
ref
.
fRRectOrOvalIsCCW
;
fRRectOrOvalStartIdx
=
ref
.
fRRectOrOvalStartIdx
;
...
...
@@ -778,7 +714,7 @@ class PathRef {
/// points are added.
void
startEdit
()
{
fIsOval
=
false
;
fIsRRect
=
false
;
rrectRepresentation
=
null
;
fIsRect
=
false
;
cachedBounds
=
null
;
fBoundsIsDirty
=
true
;
...
...
@@ -791,7 +727,11 @@ class PathRef {
}
void
setIsRRect
(
bool
isRRect
,
bool
isCCW
,
int
start
,
ui
.
RRect
rrect
)
{
fIsRRect
=
isRRect
;
if
(
isRRect
)
{
rrectRepresentation
=
rrect
;
}
else
{
rrectRepresentation
=
null
;
}
fRRectOrOvalIsCCW
=
isCCW
;
fRRectOrOvalStartIdx
=
start
;
}
...
...
@@ -813,7 +753,11 @@ class PathRef {
bool
fIsFinite
=
true
;
// only meaningful if bounds are valid
bool
fIsOval
=
false
;
bool
fIsRRect
=
false
;
/// If the path is made of a single `RRect`, this field contains the original
/// `RRect` that was added to the path.
ui
.
RRect
?
rrectRepresentation
;
bool
fIsRect
=
false
;
// Both the circle and rrect special cases have a notion of direction and starting point
// The next two variables store that information for either.
...
...
@@ -822,9 +766,9 @@ class PathRef {
int
fSegmentMask
=
0
;
bool
get
isValid
{
if
(
fIsOval
||
fIsRRect
)
{
if
(
fIsOval
||
rrectRepresentation
!=
null
)
{
// Currently we don't allow both of these to be set.
if
(
fIsOval
==
fIsRRect
)
{
if
(
fIsOval
==
(
rrectRepresentation
!=
null
)
)
{
return
false
;
}
if
(
fIsOval
)
{
...
...
@@ -838,7 +782,7 @@ class PathRef {
}
}
if
(
fIsRect
)
{
if
(
fIsOval
||
fIsRRect
)
{
if
(
fIsOval
||
(
rrectRepresentation
!=
null
)
)
{
return
false
;
}
if
(
fRRectOrOvalStartIdx
>=
4
)
{
...
...
@@ -1064,10 +1008,3 @@ class PathRefIterator {
?
pathRef
.
_fVerbs
[
_verbIndex
]
:
SPath
.
kDoneVerb
;
}
class
_Corner
{
static
const
int
kUpperLeft
=
0
;
static
const
int
kUpperRight
=
1
;
static
const
int
kLowerRight
=
2
;
static
const
int
kLowerLeft
=
3
;
}
lib/web_ui/test/engine/surface/path/path_ref_test.dart
0 → 100644
浏览文件 @
e763e567
// 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.
// @dart=2.12
import
'package:ui/src/engine.dart'
;
import
'package:test/bootstrap/browser.dart'
;
import
'package:test/test.dart'
;
import
'package:ui/ui.dart'
;
void
main
(
)
{
internalBootstrapBrowserTest
(()
=>
testMain
);
}
void
testMain
(
)
{
test
(
'PathRef.getRRect with radius'
,
()
{
final
SurfacePath
path
=
SurfacePath
();
final
RRect
rrect
=
RRect
.
fromLTRBR
(
0
,
0
,
10
,
10
,
Radius
.
circular
(
2
));
path
.
addRRect
(
rrect
);
expect
(
path
.
toRoundedRect
(),
rrect
);
});
test
(
'PathRef.getRRect with radius larger than rect'
,
()
{
final
SurfacePath
path
=
SurfacePath
();
final
RRect
rrect
=
RRect
.
fromLTRBR
(
0
,
0
,
10
,
10
,
Radius
.
circular
(
20
));
path
.
addRRect
(
rrect
);
expect
(
path
.
toRoundedRect
(),
// Path.addRRect will correct the radius to fit the dimensions, so when
// extracting the rrect out of the path we don't get the original.
RRect
.
fromLTRBR
(
0
,
0
,
10
,
10
,
Radius
.
circular
(
5
)),
);
});
test
(
'PathRef.getRRect with zero radius'
,
()
{
final
SurfacePath
path
=
SurfacePath
();
final
RRect
rrect
=
RRect
.
fromLTRBR
(
0
,
0
,
10
,
10
,
Radius
.
circular
(
0
));
path
.
addRRect
(
rrect
);
expect
(
path
.
toRoundedRect
(),
isNull
);
expect
(
path
.
toRect
(),
rrect
.
outerRect
);
});
test
(
'PathRef.getRRect elliptical'
,
()
{
final
SurfacePath
path
=
SurfacePath
();
final
RRect
rrect
=
RRect
.
fromLTRBR
(
0
,
0
,
10
,
10
,
Radius
.
elliptical
(
2
,
4
));
path
.
addRRect
(
rrect
);
expect
(
path
.
toRoundedRect
(),
rrect
);
});
test
(
'PathRef.getRRect elliptical zero x'
,
()
{
final
SurfacePath
path
=
SurfacePath
();
final
RRect
rrect
=
RRect
.
fromLTRBR
(
0
,
0
,
10
,
10
,
Radius
.
elliptical
(
0
,
3
));
path
.
addRRect
(
rrect
);
expect
(
path
.
toRoundedRect
(),
isNull
);
expect
(
path
.
toRect
(),
rrect
.
outerRect
);
});
test
(
'PathRef.getRRect elliptical zero y'
,
()
{
final
SurfacePath
path
=
SurfacePath
();
final
RRect
rrect
=
RRect
.
fromLTRBR
(
0
,
0
,
10
,
10
,
Radius
.
elliptical
(
3
,
0
));
path
.
addRRect
(
rrect
);
expect
(
path
.
toRoundedRect
(),
isNull
);
expect
(
path
.
toRect
(),
rrect
.
outerRect
);
});
test
(
'PathRef.getRRect with nearly zero corner'
,
()
{
final
SurfacePath
path
=
SurfacePath
();
final
RRect
original
=
RRect
.
fromLTRBR
(
0
,
0
,
10
,
10
,
Radius
.
elliptical
(
0.00000001
,
5
));
path
.
addRRect
(
original
);
expect
(
path
.
toRoundedRect
(),
original
);
});
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录