Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
sxychenjing
engine
提交
1ad67652
E
engine
项目概览
sxychenjing
/
engine
与 Fork 源项目一致
从无法访问的项目Fork
通知
3
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 搜索 >>
未验证
提交
1ad67652
编写于
10月 30, 2020
作者:
F
Ferhat
提交者:
GitHub
10月 30, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[web] Fixes canvas pixelation and overallocation due to transforms. (#22160)
上级
37d766c0
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
268 addition
and
55 deletion
+268
-55
lib/web_ui/lib/src/engine/bitmap_canvas.dart
lib/web_ui/lib/src/engine/bitmap_canvas.dart
+10
-4
lib/web_ui/lib/src/engine/canvas_pool.dart
lib/web_ui/lib/src/engine/canvas_pool.dart
+69
-26
lib/web_ui/lib/src/engine/html/picture.dart
lib/web_ui/lib/src/engine/html/picture.dart
+102
-6
lib/web_ui/lib/src/engine/html/shaders/shader.dart
lib/web_ui/lib/src/engine/html/shaders/shader.dart
+5
-5
lib/web_ui/lib/src/engine/html/surface.dart
lib/web_ui/lib/src/engine/html/surface.dart
+17
-13
lib/web_ui/test/engine/surface/scene_builder_test.dart
lib/web_ui/test/engine/surface/scene_builder_test.dart
+64
-0
lib/web_ui/test/golden_tests/engine/shadow_golden_test.dart
lib/web_ui/test/golden_tests/engine/shadow_golden_test.dart
+1
-1
未找到文件。
lib/web_ui/lib/src/engine/bitmap_canvas.dart
浏览文件 @
1ad67652
...
...
@@ -104,18 +104,23 @@ class BitmapCanvas extends EngineCanvas {
/// can be constructed from contents.
bool
_preserveImageData
=
false
;
/// Canvas pixel to screen pixel ratio. Similar to dpi but
/// uses global transform of canvas to compute ratio.
final
double
_density
;
/// Allocates a canvas with enough memory to paint a picture within the given
/// [bounds].
///
/// This canvas can be reused by pictures with different paint bounds as long
/// as the [Rect.size] of the bounds fully fit within the size used to
/// initialize this canvas.
BitmapCanvas
(
this
.
_bounds
)
BitmapCanvas
(
this
.
_bounds
,
{
double
density
=
1.0
}
)
:
assert
(
_bounds
!=
null
),
// ignore: unnecessary_null_comparison
_density
=
density
,
_widthInBitmapPixels
=
_widthToPhysical
(
_bounds
.
width
),
_heightInBitmapPixels
=
_heightToPhysical
(
_bounds
.
height
),
_canvasPool
=
_CanvasPool
(
_widthToPhysical
(
_bounds
.
width
),
_heightToPhysical
(
_bounds
.
height
))
{
_heightToPhysical
(
_bounds
.
height
)
,
density
)
{
rootElement
.
style
.
position
=
'absolute'
;
// Adds one extra pixel to the requested size. This is to compensate for
// _initializeViewport() snapping canvas position to 1 pixel, causing
...
...
@@ -179,10 +184,11 @@ class BitmapCanvas extends EngineCanvas {
}
// Used by picture to assess if canvas is large enough to reuse as is.
bool
doesFitBounds
(
ui
.
Rect
newBounds
)
{
bool
doesFitBounds
(
ui
.
Rect
newBounds
,
double
newDensity
)
{
assert
(
newBounds
!=
null
);
// ignore: unnecessary_null_comparison
return
_widthInBitmapPixels
>=
_widthToPhysical
(
newBounds
.
width
)
&&
_heightInBitmapPixels
>=
_heightToPhysical
(
newBounds
.
height
);
_heightInBitmapPixels
>=
_heightToPhysical
(
newBounds
.
height
)
&&
_density
==
newDensity
;
}
@override
...
...
lib/web_ui/lib/src/engine/canvas_pool.dart
浏览文件 @
1ad67652
...
...
@@ -33,8 +33,10 @@ class _CanvasPool extends _SaveStackTracking {
html
.
HtmlElement
?
_rootElement
;
int
_saveContextCount
=
0
;
final
double
_density
;
_CanvasPool
(
this
.
_widthInBitmapPixels
,
this
.
_heightInBitmapPixels
);
_CanvasPool
(
this
.
_widthInBitmapPixels
,
this
.
_heightInBitmapPixels
,
this
.
_density
);
html
.
CanvasRenderingContext2D
get
context
{
html
.
CanvasRenderingContext2D
?
ctx
=
_context
;
...
...
@@ -83,7 +85,12 @@ class _CanvasPool extends _SaveStackTracking {
void
_createCanvas
()
{
bool
requiresClearRect
=
false
;
bool
reused
=
false
;
html
.
CanvasElement
canvas
;
html
.
CanvasElement
?
canvas
;
if
(
_canvas
!=
null
)
{
_canvas
!.
width
=
0
;
_canvas
!.
height
=
0
;
_canvas
=
null
;
}
if
(
_reusablePool
!=
null
&&
_reusablePool
!.
isNotEmpty
)
{
canvas
=
_canvas
=
_reusablePool
!.
removeAt
(
0
);
requiresClearRect
=
true
;
...
...
@@ -99,10 +106,7 @@ class _CanvasPool extends _SaveStackTracking {
_widthInBitmapPixels
/
EnginePlatformDispatcher
.
browserDevicePixelRatio
;
final
double
cssHeight
=
_heightInBitmapPixels
/
EnginePlatformDispatcher
.
browserDevicePixelRatio
;
canvas
=
html
.
CanvasElement
(
width:
_widthInBitmapPixels
,
height:
_heightInBitmapPixels
,
);
canvas
=
_allocCanvas
(
_widthInBitmapPixels
,
_heightInBitmapPixels
);
_canvas
=
canvas
;
// Why is this null check here, even though we just allocated a canvas element above?
...
...
@@ -113,12 +117,9 @@ class _CanvasPool extends _SaveStackTracking {
if
(
_canvas
==
null
)
{
// Evict BitmapCanvas(s) and retry.
_reduceCanvasMemoryUsage
();
canvas
=
html
.
CanvasElement
(
width:
_widthInBitmapPixels
,
height:
_heightInBitmapPixels
,
);
canvas
=
_allocCanvas
(
_widthInBitmapPixels
,
_heightInBitmapPixels
);
}
canvas
.
style
canvas
!
.
style
..
position
=
'absolute'
..
width
=
'
${cssWidth}
px'
..
height
=
'
${cssHeight}
px'
;
...
...
@@ -131,19 +132,55 @@ class _CanvasPool extends _SaveStackTracking {
_rootElement
!.
append
(
canvas
);
}
if
(
reused
)
{
// If a canvas is the first element we set z-index = -1 in [BitmapCanvas]
// endOfPaint to workaround blink compositing bug. To make sure this
// does not leak when reused reset z-index.
canvas
.
style
.
removeProperty
(
'z-index'
);
try
{
if
(
reused
)
{
// If a canvas is the first element we set z-index = -1 in [BitmapCanvas]
// endOfPaint to workaround blink compositing bug. To make sure this
// does not leak when reused reset z-index.
canvas
.
style
.
removeProperty
(
'z-index'
);
}
_context
=
canvas
.
context2D
;
}
catch
(
e
)
{
// Handle OOM.
}
final
html
.
CanvasRenderingContext2D
context
=
_context
=
canvas
.
context2D
;
_contextHandle
=
ContextStateHandle
(
this
,
context
);
if
(
_context
==
null
)
{
_reduceCanvasMemoryUsage
();
_context
=
canvas
.
context2D
;
}
if
(
_context
==
null
)
{
/// Browser ran out of memory, try to recover current allocation
/// and bail.
_canvas
?.
width
=
0
;
_canvas
?.
height
=
0
;
_canvas
=
null
;
return
;
}
_contextHandle
=
ContextStateHandle
(
this
,
_context
!,
this
.
_density
);
_initializeViewport
(
requiresClearRect
);
_replayClipStack
();
}
html
.
CanvasElement
?
_allocCanvas
(
int
width
,
int
height
)
{
final
dynamic
canvas
=
js_util
.
callMethod
(
html
.
document
,
'createElement'
,
<
dynamic
>[
'CANVAS'
]);
if
(
canvas
!=
null
)
{
try
{
canvas
.
width
=
(
width
*
_density
).
ceil
();
canvas
.
height
=
(
height
*
_density
).
ceil
();
}
catch
(
e
)
{
return
null
;
}
return
canvas
as
html
.
CanvasElement
;
}
return
null
;
// !!! We don't use the code below since NNBD assumes it can never return
// null and optimizes out code.
// return canvas = html.CanvasElement(
// width: _widthInBitmapPixels,
// height: _heightInBitmapPixels,
// );
}
@override
void
clear
()
{
super
.
clear
();
...
...
@@ -188,7 +225,7 @@ class _CanvasPool extends _SaveStackTracking {
clipTimeTransform
[
5
]
!=
prevTransform
[
5
]
||
clipTimeTransform
[
12
]
!=
prevTransform
[
12
]
||
clipTimeTransform
[
13
]
!=
prevTransform
[
13
])
{
final
double
ratio
=
EnginePlatformDispatcher
.
browserDevicePixelRatio
;
final
double
ratio
=
dpi
;
ctx
.
setTransform
(
ratio
,
0
,
0
,
ratio
,
0
,
0
);
ctx
.
transform
(
clipTimeTransform
[
0
],
...
...
@@ -222,7 +259,7 @@ class _CanvasPool extends _SaveStackTracking {
transform
[
5
]
!=
prevTransform
[
5
]
||
transform
[
12
]
!=
prevTransform
[
12
]
||
transform
[
13
]
!=
prevTransform
[
13
])
{
final
double
ratio
=
EnginePlatformDispatcher
.
browserDevicePixelRatio
;
final
double
ratio
=
dpi
;
ctx
.
setTransform
(
ratio
,
0
,
0
,
ratio
,
0
,
0
);
ctx
.
transform
(
transform
[
0
],
transform
[
1
],
transform
[
4
],
transform
[
5
],
transform
[
12
],
transform
[
13
]);
...
...
@@ -300,15 +337,19 @@ class _CanvasPool extends _SaveStackTracking {
// is applied on the DOM elements.
ctx
.
setTransform
(
1
,
0
,
0
,
1
,
0
,
0
);
if
(
clearCanvas
)
{
ctx
.
clearRect
(
0
,
0
,
_widthInBitmapPixels
,
_heightInBitmapPixels
);
ctx
.
clearRect
(
0
,
0
,
_widthInBitmapPixels
*
_density
,
_heightInBitmapPixels
*
_density
);
}
// This scale makes sure that 1 CSS pixel is translated to the correct
// number of bitmap pixels.
ctx
.
scale
(
EnginePlatformDispatcher
.
browserDevicePixelRatio
,
EnginePlatformDispatcher
.
browserDevicePixelRatio
);
ctx
.
scale
(
dpi
,
dpi
);
}
/// Returns effective dpi (browser DPI and pixel density due to transform).
double
get
dpi
=>
EnginePlatformDispatcher
.
browserDevicePixelRatio
*
_density
;
void
resetTransform
()
{
final
html
.
CanvasElement
?
canvas
=
_canvas
;
if
(
canvas
!=
null
)
{
...
...
@@ -688,8 +729,9 @@ class _CanvasPool extends _SaveStackTracking {
class
ContextStateHandle
{
final
html
.
CanvasRenderingContext2D
context
;
final
_CanvasPool
_canvasPool
;
final
double
density
;
ContextStateHandle
(
this
.
_canvasPool
,
this
.
context
);
ContextStateHandle
(
this
.
_canvasPool
,
this
.
context
,
this
.
density
);
ui
.
BlendMode
?
_currentBlendMode
=
ui
.
BlendMode
.
srcOver
;
ui
.
StrokeCap
?
_currentStrokeCap
=
ui
.
StrokeCap
.
butt
;
ui
.
StrokeJoin
?
_currentStrokeJoin
=
ui
.
StrokeJoin
.
miter
;
...
...
@@ -778,7 +820,8 @@ class ContextStateHandle {
if
(
paint
.
shader
!=
null
)
{
final
EngineGradient
engineShader
=
paint
.
shader
as
EngineGradient
;
final
Object
paintStyle
=
engineShader
.
createPaintStyle
(
_canvasPool
.
context
,
shaderBounds
);
engineShader
.
createPaintStyle
(
_canvasPool
.
context
,
shaderBounds
,
density
);
fillStyle
=
paintStyle
;
strokeStyle
=
paintStyle
;
}
else
if
(
paint
.
color
!=
null
)
{
...
...
lib/web_ui/lib/src/engine/html/picture.dart
浏览文件 @
1ad67652
...
...
@@ -90,6 +90,7 @@ class PersistedPicture extends PersistedLeafSurface {
final
EnginePicture
picture
;
final
ui
.
Rect
?
localPaintBounds
;
final
int
hints
;
double
_density
=
1.0
;
/// Cache for reusing elements such as images across picture updates.
CrossFrameCache
<
html
.
HtmlElement
>?
_elementCache
=
...
...
@@ -107,6 +108,23 @@ class PersistedPicture extends PersistedLeafSurface {
_transform
=
_transform
!.
clone
();
_transform
!.
translate
(
dx
,
dy
);
}
final
double
paintWidth
=
localPaintBounds
!.
width
;
final
double
paintHeight
=
localPaintBounds
!.
height
;
final
double
newDensity
=
localPaintBounds
==
null
||
paintWidth
==
0
||
paintHeight
==
0
?
1.0
:
_computePixelDensity
(
_transform
,
paintWidth
,
paintHeight
);
if
(
newDensity
!=
_density
)
{
_density
=
newDensity
;
if
(
_canvas
!=
null
)
{
// If cull rect and density hasn't changed, this will only repaint.
// If density doesn't match canvas, a new canvas will be created
// and paint queued.
//
// Similar to preroll for transform where transform is updated, for
// picture this means we need to repaint so pixelation doesn't occur
// due to transform changing overall dpi.
applyPaint
(
_canvas
);
}
}
_computeExactCullRects
();
}
...
...
@@ -296,7 +314,12 @@ class PersistedPicture extends PersistedLeafSurface {
// painting. This removes all the setup work and scaffolding objects
// that won't be useful for anything anyway.
_recycleCanvas
(
oldCanvas
);
domRenderer
.
clearDom
(
rootElement
!);
if
(
rootElement
!=
null
)
{
domRenderer
.
clearDom
(
rootElement
!);
}
if
(
_canvas
!=
null
)
{
_recycleCanvas
(
_canvas
);
}
_canvas
=
null
;
return
;
}
...
...
@@ -339,7 +362,7 @@ class PersistedPicture extends PersistedLeafSurface {
// We did not allocate a canvas last time. This can happen when the
// picture is completely clipped out of the view.
return
1.0
;
}
else
if
(!
oldCanvas
.
doesFitBounds
(
_exactLocalCullRect
!))
{
}
else
if
(!
oldCanvas
.
doesFitBounds
(
_exactLocalCullRect
!
,
_density
))
{
// The canvas needs to be resized before painting.
return
1.0
;
}
else
{
...
...
@@ -382,7 +405,7 @@ class PersistedPicture extends PersistedLeafSurface {
void
_applyBitmapPaint
(
EngineCanvas
?
oldCanvas
)
{
if
(
oldCanvas
is
BitmapCanvas
&&
oldCanvas
.
doesFitBounds
(
_optimalLocalCullRect
!)
&&
oldCanvas
.
doesFitBounds
(
_optimalLocalCullRect
!
,
_density
)
&&
oldCanvas
.
isReusable
())
{
if
(
_debugShowCanvasReuseStats
)
{
DebugCanvasReuseOverlay
.
instance
.
keptCount
++;
...
...
@@ -451,7 +474,7 @@ class PersistedPicture extends PersistedLeafSurface {
final
double
candidatePixelCount
=
candidateSize
.
width
*
candidateSize
.
height
;
final
bool
fits
=
candidate
.
doesFitBounds
(
bounds
);
final
bool
fits
=
candidate
.
doesFitBounds
(
bounds
,
_density
);
final
bool
isSmaller
=
candidatePixelCount
<
lastPixelCount
;
if
(
fits
&&
isSmaller
)
{
// [isTooSmall] is used to make sure that a small picture doesn't
...
...
@@ -493,7 +516,7 @@ class PersistedPicture extends PersistedLeafSurface {
if
(
_debugShowCanvasReuseStats
)
{
DebugCanvasReuseOverlay
.
instance
.
createdCount
++;
}
final
BitmapCanvas
canvas
=
BitmapCanvas
(
bounds
);
final
BitmapCanvas
canvas
=
BitmapCanvas
(
bounds
,
density:
_density
);
canvas
.
setElementCache
(
_elementCache
);
if
(
_debugExplainSurfaceStats
)
{
_surfaceStatsFor
(
this
)
...
...
@@ -536,8 +559,12 @@ class PersistedPicture extends PersistedLeafSurface {
final
bool
cullRectChangeRequiresRepaint
=
_computeOptimalCullRect
(
oldSurface
);
if
(
identical
(
picture
,
oldSurface
.
picture
))
{
bool
densityChanged
=
(
_canvas
is
BitmapCanvas
&&
_density
!=
(
_canvas
as
BitmapCanvas
).
_density
);
// The picture is the same. Attempt to avoid repaint.
if
(
cullRectChangeRequiresRepaint
)
{
if
(
cullRectChangeRequiresRepaint
||
densityChanged
)
{
// Cull rect changed such that a repaint is still necessary.
_applyPaint
(
oldSurface
);
}
else
{
...
...
@@ -603,3 +630,72 @@ class PersistedPicture extends PersistedLeafSurface {
}
}
}
/// Given size of a rectangle and transform, computes pixel density
/// (scale factor).
double
_computePixelDensity
(
Matrix4
?
transform
,
double
width
,
double
height
)
{
if
(
transform
==
null
||
transform
.
isIdentity
())
{
return
1.0
;
}
final
Float32List
m
=
transform
.
storage
;
// Apply perspective transform to all 4 corners. Can't use left,top, bottom,
// right since for example rotating 45 degrees would yield inaccurate size.
double
minX
=
m
[
12
]
*
m
[
15
];
double
minY
=
m
[
13
]
*
m
[
15
];
double
maxX
=
minX
;
double
maxY
=
minY
;
double
x
=
width
;
double
y
=
height
;
double
wp
=
1.0
/
((
m
[
3
]
*
x
)
+
(
m
[
7
]
*
y
)
+
m
[
15
]);
double
xp
=
((
m
[
0
]
*
x
)
+
(
m
[
4
]
*
y
)
+
m
[
12
])
*
wp
;
double
yp
=
((
m
[
1
]
*
x
)
+
(
m
[
5
]
*
y
)
+
m
[
13
])
*
wp
;
print
(
'
$xp
,
$yp
'
);
minX
=
math
.
min
(
minX
,
xp
);
maxX
=
math
.
max
(
maxX
,
xp
);
minY
=
math
.
min
(
minY
,
yp
);
maxY
=
math
.
max
(
maxY
,
yp
);
x
=
0
;
wp
=
1.0
/
((
m
[
3
]
*
x
)
+
(
m
[
7
]
*
y
)
+
m
[
15
]);
xp
=
((
m
[
0
]
*
x
)
+
(
m
[
4
]
*
y
)
+
m
[
12
])
*
wp
;
yp
=
((
m
[
1
]
*
x
)
+
(
m
[
5
]
*
y
)
+
m
[
13
])
*
wp
;
print
(
'
$xp
,
$yp
'
);
minX
=
math
.
min
(
minX
,
xp
);
maxX
=
math
.
max
(
maxX
,
xp
);
minY
=
math
.
min
(
minY
,
yp
);
maxY
=
math
.
max
(
maxY
,
yp
);
x
=
width
;
y
=
0
;
wp
=
1.0
/
((
m
[
3
]
*
x
)
+
(
m
[
7
]
*
y
)
+
m
[
15
]);
xp
=
((
m
[
0
]
*
x
)
+
(
m
[
4
]
*
y
)
+
m
[
12
])
*
wp
;
yp
=
((
m
[
1
]
*
x
)
+
(
m
[
5
]
*
y
)
+
m
[
13
])
*
wp
;
print
(
'
$xp
,
$yp
'
);
minX
=
math
.
min
(
minX
,
xp
);
maxX
=
math
.
max
(
maxX
,
xp
);
minY
=
math
.
min
(
minY
,
yp
);
maxY
=
math
.
max
(
maxY
,
yp
);
double
scaleX
=
(
maxX
-
minX
)
/
width
;
double
scaleY
=
(
maxY
-
minY
)
/
height
;
double
scale
=
math
.
min
(
scaleX
,
scaleY
);
// kEpsilon guards against divide by zero below.
if
(
scale
<
kEpsilon
||
scale
==
1
)
{
// Handle local paint bounds scaled to 0, typical when using
// transform animations and nothing is drawn.
return
1.0
;
}
if
(
scale
>
1
)
{
// Normalize scale to multiples of 2: 1x, 2x, 4x, 6x, 8x.
// This is to prevent frequent rescaling of canvas during animations.
//
// On a fullscreen high dpi device dpi*density*resolution will demand
// too much memory, so clamp at 4.
scale
=
math
.
min
(
4.0
,
((
scale
/
2.0
).
ceil
()
*
2.0
));
// Guard against webkit absolute limit.
const
double
kPixelLimit
=
1024
*
1024
*
4
;
if
((
width
*
height
*
scale
*
scale
)
>
kPixelLimit
&&
scale
>
2
)
{
scale
=
(
kPixelLimit
*
0.8
)
/
(
width
*
height
);
}
}
else
{
scale
=
math
.
max
(
2.0
/
(
2.0
/
scale
).
floor
(),
0.0001
);
}
return
scale
;
}
lib/web_ui/lib/src/engine/html/shaders/shader.dart
浏览文件 @
1ad67652
...
...
@@ -11,7 +11,7 @@ abstract class EngineGradient implements ui.Gradient {
/// Creates a fill style to be used in painting.
Object
createPaintStyle
(
html
.
CanvasRenderingContext2D
?
ctx
,
ui
.
Rect
?
shaderBounds
);
ui
.
Rect
?
shaderBounds
,
double
density
);
}
class
GradientSweep
extends
EngineGradient
{
...
...
@@ -29,7 +29,7 @@ class GradientSweep extends EngineGradient {
@override
Object
createPaintStyle
(
html
.
CanvasRenderingContext2D
?
ctx
,
ui
.
Rect
?
shaderBounds
)
{
ui
.
Rect
?
shaderBounds
,
double
density
)
{
assert
(
shaderBounds
!=
null
);
int
widthInPixels
=
shaderBounds
!.
right
.
ceil
();
int
heightInPixels
=
shaderBounds
.
bottom
.
ceil
();
...
...
@@ -167,7 +167,7 @@ class GradientLinear extends EngineGradient {
@override
html
.
CanvasGradient
createPaintStyle
(
html
.
CanvasRenderingContext2D
?
ctx
,
ui
.
Rect
?
shaderBounds
)
{
ui
.
Rect
?
shaderBounds
,
double
density
)
{
_FastMatrix64
?
matrix4
=
this
.
matrix4
;
html
.
CanvasGradient
gradient
;
if
(
matrix4
!=
null
)
{
...
...
@@ -215,7 +215,7 @@ class GradientRadial extends EngineGradient {
@override
Object
createPaintStyle
(
html
.
CanvasRenderingContext2D
?
ctx
,
ui
.
Rect
?
shaderBounds
)
{
ui
.
Rect
?
shaderBounds
,
double
density
)
{
if
(!
useCanvasKit
)
{
if
(
tileMode
!=
ui
.
TileMode
.
clamp
)
{
throw
UnimplementedError
(
...
...
@@ -255,7 +255,7 @@ class GradientConical extends EngineGradient {
@override
Object
createPaintStyle
(
html
.
CanvasRenderingContext2D
?
ctx
,
ui
.
Rect
?
shaderBounds
)
{
ui
.
Rect
?
shaderBounds
,
double
density
)
{
throw
UnimplementedError
();
}
}
...
...
lib/web_ui/lib/src/engine/html/surface.dart
浏览文件 @
1ad67652
...
...
@@ -33,21 +33,24 @@ const double _kScreenPixelRatioWarningThreshold = 6.0;
/// Performs any outstanding painting work enqueued by [PersistedPicture]s.
void
commitScene
(
PersistedScene
scene
)
{
if
(
_paintQueue
.
isNotEmpty
)
{
if
(
_paintQueue
.
length
>
1
)
{
// Sort paint requests in decreasing canvas size order. Paint requests
// attempt to reuse canvases. For efficiency we want the biggest pictures
// to find canvases before the smaller ones claim them.
_paintQueue
.
sort
((
_PaintRequest
a
,
_PaintRequest
b
)
{
final
double
aSize
=
a
.
canvasSize
.
height
*
a
.
canvasSize
.
width
;
final
double
bSize
=
b
.
canvasSize
.
height
*
b
.
canvasSize
.
width
;
return
bSize
.
compareTo
(
aSize
);
});
}
try
{
if
(
_paintQueue
.
length
>
1
)
{
// Sort paint requests in decreasing canvas size order. Paint requests
// attempt to reuse canvases. For efficiency we want the biggest pictures
// to find canvases before the smaller ones claim them.
_paintQueue
.
sort
((
_PaintRequest
a
,
_PaintRequest
b
)
{
final
double
aSize
=
a
.
canvasSize
.
height
*
a
.
canvasSize
.
width
;
final
double
bSize
=
b
.
canvasSize
.
height
*
b
.
canvasSize
.
width
;
return
bSize
.
compareTo
(
aSize
);
});
}
for
(
_PaintRequest
request
in
_paintQueue
)
{
request
.
paintCallback
();
for
(
_PaintRequest
request
in
_paintQueue
)
{
request
.
paintCallback
();
}
}
finally
{
_paintQueue
=
<
_PaintRequest
>[];
}
_paintQueue
=
<
_PaintRequest
>[];
}
// After the update the retained surfaces are back to active.
...
...
@@ -356,6 +359,7 @@ abstract class PersistedSurface implements ui.EngineLayer {
assert
(
rootElement
==
null
);
assert
(
debugAssertSurfaceState
(
this
,
PersistedSurfaceState
.
created
));
rootElement
=
createElement
();
assert
(
rootElement
!=
null
);
applyWebkitClipFix
(
rootElement
);
if
(
_debugExplainSurfaceStats
)
{
_surfaceStatsFor
(
this
).
allocatedDomNodeCount
++;
...
...
lib/web_ui/test/engine/surface/scene_builder_test.dart
浏览文件 @
1ad67652
...
...
@@ -525,6 +525,70 @@ void testMain() {
await
testCase
(
'be'
,
'remove in the middle'
,
deletions:
2
);
await
testCase
(
''
,
'remove all'
,
deletions:
2
);
});
test
(
'Canvas should allocate fewer pixels when zoomed out'
,
()
async
{
final
SurfaceSceneBuilder
builder
=
SurfaceSceneBuilder
();
final
Picture
picture1
=
_drawPicture
();
builder
.
pushClipRect
(
const
Rect
.
fromLTRB
(
10
,
10
,
300
,
300
));
builder
.
addPicture
(
Offset
.
zero
,
picture1
);
builder
.
pop
();
html
.
HtmlElement
content
=
builder
.
build
().
webOnlyRootElement
;
html
.
CanvasElement
canvas
=
content
.
querySelector
(
'canvas'
);
final
int
unscaledWidth
=
canvas
.
width
;
final
int
unscaledHeight
=
canvas
.
height
;
// Force update to scene which will utilize reuse code path.
final
SurfaceSceneBuilder
builder2
=
SurfaceSceneBuilder
();
builder2
.
pushOffset
(
0
,
0
);
builder2
.
pushTransform
(
Matrix4
.
identity
().
scaled
(
0.5
,
0.5
).
toFloat64
());
builder2
.
pushClipRect
(
const
Rect
.
fromLTRB
(
10
,
10
,
300
,
300
),
);
builder2
.
addPicture
(
Offset
.
zero
,
picture1
);
builder2
.
pop
();
builder2
.
pop
();
builder2
.
pop
();
html
.
HtmlElement
contentAfterScale
=
builder2
.
build
().
webOnlyRootElement
;
html
.
CanvasElement
canvas2
=
contentAfterScale
.
querySelector
(
'canvas'
);
// Although we are drawing same picture, due to scaling the new canvas
// should have fewer pixels.
expect
(
canvas2
.
width
<
unscaledWidth
,
true
);
expect
(
canvas2
.
height
<
unscaledHeight
,
true
);
});
test
(
'Canvas should allocate more pixels when zoomed in'
,
()
async
{
final
SurfaceSceneBuilder
builder
=
SurfaceSceneBuilder
();
final
Picture
picture1
=
_drawPicture
();
builder
.
pushClipRect
(
const
Rect
.
fromLTRB
(
10
,
10
,
300
,
300
));
builder
.
addPicture
(
Offset
.
zero
,
picture1
);
builder
.
pop
();
html
.
HtmlElement
content
=
builder
.
build
().
webOnlyRootElement
;
html
.
CanvasElement
canvas
=
content
.
querySelector
(
'canvas'
);
final
int
unscaledWidth
=
canvas
.
width
;
final
int
unscaledHeight
=
canvas
.
height
;
// Force update to scene which will utilize reuse code path.
final
SurfaceSceneBuilder
builder2
=
SurfaceSceneBuilder
();
builder2
.
pushOffset
(
0
,
0
);
builder2
.
pushTransform
(
Matrix4
.
identity
().
scaled
(
2
,
2
).
toFloat64
());
builder2
.
pushClipRect
(
const
Rect
.
fromLTRB
(
10
,
10
,
300
,
300
),
);
builder2
.
addPicture
(
Offset
.
zero
,
picture1
);
builder2
.
pop
();
builder2
.
pop
();
builder2
.
pop
();
html
.
HtmlElement
contentAfterScale
=
builder2
.
build
().
webOnlyRootElement
;
html
.
CanvasElement
canvas2
=
contentAfterScale
.
querySelector
(
'canvas'
);
// Although we are drawing same picture, due to scaling the new canvas
// should have more pixels.
expect
(
canvas2
.
width
>
unscaledWidth
,
true
);
expect
(
canvas2
.
height
>
unscaledHeight
,
true
);
});
}
typedef
TestLayerBuilder
=
EngineLayer
Function
(
...
...
lib/web_ui/test/golden_tests/engine/shadow_golden_test.dart
浏览文件 @
1ad67652
...
...
@@ -163,7 +163,7 @@ void testMain() async {
await
matchGoldenFile
(
'shadows.png'
,
region:
region
,
maxDiffRatePercent:
0.
0
,
maxDiffRatePercent:
0.
23
,
pixelComparison:
PixelComparison
.
precise
,
);
},
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录