Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
qq_34031325
engine
提交
93cb5dbb
E
engine
项目概览
qq_34031325
/
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,发现更多精彩内容 >>
未验证
提交
93cb5dbb
编写于
2月 24, 2021
作者:
F
Ferhat
提交者:
GitHub
2月 24, 2021
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[web] Implement Canvas.drawPicture (#24574)
上级
e9c676f1
变更
6
展开全部
隐藏空白更改
内联
并排
Showing
6 changed file
with
390 addition
and
183 deletion
+390
-183
lib/web_ui/dev/goldens_lock.yaml
lib/web_ui/dev/goldens_lock.yaml
+1
-1
lib/web_ui/lib/src/engine/bitmap_canvas.dart
lib/web_ui/lib/src/engine/bitmap_canvas.dart
+0
-6
lib/web_ui/lib/src/engine/html/canvas.dart
lib/web_ui/lib/src/engine/html/canvas.dart
+1
-2
lib/web_ui/lib/src/engine/html/recording_canvas.dart
lib/web_ui/lib/src/engine/html/recording_canvas.dart
+91
-3
lib/web_ui/lib/src/engine/html/shaders/shader.dart
lib/web_ui/lib/src/engine/html/shaders/shader.dart
+206
-118
lib/web_ui/test/golden_tests/engine/canvas_draw_picture_test.dart
...ui/test/golden_tests/engine/canvas_draw_picture_test.dart
+91
-53
未找到文件。
lib/web_ui/dev/goldens_lock.yaml
浏览文件 @
93cb5dbb
repository
:
https://github.com/flutter/goldens.git
repository
:
https://github.com/flutter/goldens.git
revision
:
041056fc3ae057574586fa6f69b2cc9465c4a5bf
revision
:
bb55871d3803337053f7200b8690a4c1322e82ea
lib/web_ui/lib/src/engine/bitmap_canvas.dart
浏览文件 @
93cb5dbb
...
@@ -923,12 +923,6 @@ class BitmapCanvas extends EngineCanvas {
...
@@ -923,12 +923,6 @@ class BitmapCanvas extends EngineCanvas {
_closeCurrentCanvas
();
_closeCurrentCanvas
();
}
}
/// Paints the [picture] into this canvas.
void
drawPicture
(
ui
.
Picture
picture
)
{
final
EnginePicture
enginePicture
=
picture
as
EnginePicture
;
enginePicture
.
recordingCanvas
!.
apply
(
this
,
bounds
);
}
/// Draws vertices on a gl context.
/// Draws vertices on a gl context.
///
///
/// If both colors and textures is specified in paint data,
/// If both colors and textures is specified in paint data,
...
...
lib/web_ui/lib/src/engine/html/canvas.dart
浏览文件 @
93cb5dbb
...
@@ -444,8 +444,7 @@ class SurfaceCanvas implements ui.Canvas {
...
@@ -444,8 +444,7 @@ class SurfaceCanvas implements ui.Canvas {
void
drawPicture
(
ui
.
Picture
picture
)
{
void
drawPicture
(
ui
.
Picture
picture
)
{
// ignore: unnecessary_null_comparison
// ignore: unnecessary_null_comparison
assert
(
picture
!=
null
);
// picture is checked on the engine side
assert
(
picture
!=
null
);
// picture is checked on the engine side
// TODO(het): Support this
_canvas
.
drawPicture
(
picture
);
throw
UnimplementedError
();
}
}
@override
@override
...
...
lib/web_ui/lib/src/engine/html/recording_canvas.dart
浏览文件 @
93cb5dbb
...
@@ -120,13 +120,25 @@ class RecordingCanvas {
...
@@ -120,13 +120,25 @@ class RecordingCanvas {
_recordingEnded
=
true
;
_recordingEnded
=
true
;
}
}
/// Applies the recorded commands onto an [engineCanvas].
/// Applies the recorded commands onto an [engineCanvas] and signals to
/// canvas that all painting is completed for garbage collection/reuse.
///
///
/// The [clipRect] specifies the clip applied to the picture (screen clip at
/// The [clipRect] specifies the clip applied to the picture (screen clip at
/// a minimum). The commands that fall outside the clip are skipped and are
/// a minimum). The commands that fall outside the clip are skipped and are
/// not applied to the [engineCanvas]. A command must have a non-zero
/// not applied to the [engineCanvas]. A command must have a non-zero
/// intersection with the clip in order to be applied.
/// intersection with the clip in order to be applied.
void
apply
(
EngineCanvas
engineCanvas
,
ui
.
Rect
clipRect
)
{
void
apply
(
EngineCanvas
engineCanvas
,
ui
.
Rect
clipRect
)
{
applyCommands
(
engineCanvas
,
clipRect
);
engineCanvas
.
endOfPaint
();
}
/// Applies the recorded commands onto an [engineCanvas].
///
/// The [clipRect] specifies the clip applied to the picture (screen clip at
/// a minimum). The commands that fall outside the clip are skipped and are
/// not applied to the [engineCanvas]. A command must have a non-zero
/// intersection with the clip in order to be applied.
void
applyCommands
(
EngineCanvas
engineCanvas
,
ui
.
Rect
clipRect
)
{
assert
(
_recordingEnded
);
assert
(
_recordingEnded
);
if
(
_debugDumpPaintCommands
)
{
if
(
_debugDumpPaintCommands
)
{
final
StringBuffer
debugBuf
=
StringBuffer
();
final
StringBuffer
debugBuf
=
StringBuffer
();
...
@@ -183,7 +195,6 @@ class RecordingCanvas {
...
@@ -183,7 +195,6 @@ class RecordingCanvas {
}
}
}
}
}
}
engineCanvas
.
endOfPaint
();
}
}
/// Prints recorded commands.
/// Prints recorded commands.
...
@@ -511,6 +522,29 @@ class RecordingCanvas {
...
@@ -511,6 +522,29 @@ class RecordingCanvas {
_commands
.
add
(
command
);
_commands
.
add
(
command
);
}
}
void
drawPicture
(
ui
.
Picture
picture
)
{
assert
(!
_recordingEnded
);
final
EnginePicture
enginePicture
=
picture
as
EnginePicture
;
// TODO apply renderStrategy of picture recording to this recording.
if
(
enginePicture
.
recordingCanvas
==
null
)
{
// No contents / nothing to draw.
return
;
}
final
RecordingCanvas
pictureRecording
=
enginePicture
.
recordingCanvas
!;
if
(
pictureRecording
.
_didDraw
==
true
)
{
_didDraw
=
true
;
}
renderStrategy
.
merge
(
pictureRecording
.
renderStrategy
);
// Need to save to make sure we don't pick up leftover clips and
// transforms from running commands in picture.
save
();
_commands
.
addAll
(
pictureRecording
.
_commands
);
restore
();
if
(
pictureRecording
.
_pictureBounds
!=
null
)
{
_paintBounds
.
growBounds
(
pictureRecording
.
_pictureBounds
!);
}
}
void
drawImageRect
(
void
drawImageRect
(
ui
.
Image
image
,
ui
.
Rect
src
,
ui
.
Rect
dst
,
SurfacePaint
paint
)
{
ui
.
Image
image
,
ui
.
Rect
src
,
ui
.
Rect
dst
,
SurfacePaint
paint
)
{
assert
(!
_recordingEnded
);
assert
(!
_recordingEnded
);
...
@@ -1746,7 +1780,8 @@ class _PaintBounds {
...
@@ -1746,7 +1780,8 @@ class _PaintBounds {
growLTRB
(
r
.
left
,
r
.
top
,
r
.
right
,
r
.
bottom
,
command
);
growLTRB
(
r
.
left
,
r
.
top
,
r
.
right
,
r
.
bottom
,
command
);
}
}
/// Grow painted area to include given rectangle.
/// Grow painted area to include given rectangle and precompute
/// clipped out state for command.
void
growLTRB
(
double
left
,
double
top
,
double
right
,
double
bottom
,
void
growLTRB
(
double
left
,
double
top
,
double
right
,
double
bottom
,
DrawCommand
command
)
{
DrawCommand
command
)
{
if
(
left
==
right
||
top
==
bottom
)
{
if
(
left
==
right
||
top
==
bottom
)
{
...
@@ -1826,6 +1861,52 @@ class _PaintBounds {
...
@@ -1826,6 +1861,52 @@ class _PaintBounds {
_didPaintInsideClipArea
=
true
;
_didPaintInsideClipArea
=
true
;
}
}
/// Grow painted area to include given rectangle.
void
growBounds
(
ui
.
Rect
bounds
)
{
final
double
left
=
bounds
.
left
;
final
double
top
=
bounds
.
top
;
final
double
right
=
bounds
.
right
;
final
double
bottom
=
bounds
.
bottom
;
if
(
left
==
right
||
top
==
bottom
)
{
return
;
}
double
transformedPointLeft
=
left
;
double
transformedPointTop
=
top
;
double
transformedPointRight
=
right
;
double
transformedPointBottom
=
bottom
;
if
(!
_currentMatrixIsIdentity
)
{
_tempRectData
[
0
]
=
left
;
_tempRectData
[
1
]
=
top
;
_tempRectData
[
2
]
=
right
;
_tempRectData
[
3
]
=
bottom
;
transformLTRB
(
_currentMatrix
,
_tempRectData
);
transformedPointLeft
=
_tempRectData
[
0
];
transformedPointTop
=
_tempRectData
[
1
];
transformedPointRight
=
_tempRectData
[
2
];
transformedPointBottom
=
_tempRectData
[
3
];
}
if
(
_didPaintInsideClipArea
)
{
_left
=
math
.
min
(
math
.
min
(
_left
,
transformedPointLeft
),
transformedPointRight
);
_right
=
math
.
max
(
math
.
max
(
_right
,
transformedPointLeft
),
transformedPointRight
);
_top
=
math
.
min
(
math
.
min
(
_top
,
transformedPointTop
),
transformedPointBottom
);
_bottom
=
math
.
max
(
math
.
max
(
_bottom
,
transformedPointTop
),
transformedPointBottom
);
}
else
{
_left
=
math
.
min
(
transformedPointLeft
,
transformedPointRight
);
_right
=
math
.
max
(
transformedPointLeft
,
transformedPointRight
);
_top
=
math
.
min
(
transformedPointTop
,
transformedPointBottom
);
_bottom
=
math
.
max
(
transformedPointTop
,
transformedPointBottom
);
}
_didPaintInsideClipArea
=
true
;
}
void
saveTransformsAndClip
()
{
void
saveTransformsAndClip
()
{
_transforms
.
add
(
_currentMatrix
.
clone
());
_transforms
.
add
(
_currentMatrix
.
clone
());
_clipStack
.
add
(
_clipRectInitialized
_clipStack
.
add
(
_clipRectInitialized
...
@@ -1942,4 +2023,11 @@ class RenderStrategy {
...
@@ -1942,4 +2023,11 @@ class RenderStrategy {
bool
isInsideShaderMask
=
false
;
bool
isInsideShaderMask
=
false
;
RenderStrategy
();
RenderStrategy
();
/// Merges render strategy settings from a child recording.
void
merge
(
RenderStrategy
childStrategy
)
{
hasImageElements
|=
childStrategy
.
hasImageElements
;
hasParagraphs
|=
childStrategy
.
hasParagraphs
;
hasArbitraryPaint
|=
childStrategy
.
hasArbitraryPaint
;
}
}
}
lib/web_ui/lib/src/engine/html/shaders/shader.dart
浏览文件 @
93cb5dbb
此差异已折叠。
点击以展开。
lib/web_ui/test/golden_tests/engine/canvas_draw_picture_test.dart
浏览文件 @
93cb5dbb
...
@@ -31,61 +31,90 @@ void testMain() async {
...
@@ -31,61 +31,90 @@ void testMain() async {
await
webOnlyFontCollection
.
ensureFontsLoaded
();
await
webOnlyFontCollection
.
ensureFontsLoaded
();
});
});
test
(
'draw growing picture across frames'
,
()
async
{
group
(
'Add picture to scene'
,
()
{
final
SurfaceSceneBuilder
builder
=
SurfaceSceneBuilder
();
test
(
'draw growing picture across frames'
,
()
async
{
builder
.
pushClipRect
(
final
SurfaceSceneBuilder
builder
=
SurfaceSceneBuilder
();
const
Rect
.
fromLTRB
(
0
,
0
,
100
,
100
),
builder
.
pushClipRect
(
);
const
Rect
.
fromLTRB
(
0
,
0
,
100
,
100
),
);
_drawTestPicture
(
builder
,
100
,
false
);
builder
.
pop
();
_drawTestPicture
(
builder
,
100
,
false
);
builder
.
pop
();
html
.
Element
elm1
=
builder
.
build
().
webOnlyRootElement
;
html
.
document
.
body
.
append
(
elm1
);
html
.
Element
elm1
=
builder
.
build
()
// Now draw picture again but at larger size.
.
webOnlyRootElement
;
final
SurfaceSceneBuilder
builder2
=
SurfaceSceneBuilder
();
html
.
document
.
body
.
append
(
elm1
);
builder2
.
pushClipRect
(
const
Rect
.
fromLTRB
(
0
,
0
,
100
,
100
),
// Now draw picture again but at larger size.
);
final
SurfaceSceneBuilder
builder2
=
SurfaceSceneBuilder
();
// Now draw the picture at original target size, which will use a
builder2
.
pushClipRect
(
// different code path that should normally not have width/height set
const
Rect
.
fromLTRB
(
0
,
0
,
100
,
100
),
// on image element.
);
_drawTestPicture
(
builder2
,
20
,
false
);
// Now draw the picture at original target size, which will use a
builder2
.
pop
();
// different code path that should normally not have width/height set
// on image element.
elm1
.
remove
();
_drawTestPicture
(
builder2
,
20
,
false
);
html
.
document
.
body
.
append
(
builder2
.
build
().
webOnlyRootElement
);
builder2
.
pop
();
await
matchGoldenFile
(
'canvas_draw_picture_acrossframes.png'
,
elm1
.
remove
();
region:
region
);
html
.
document
.
body
.
append
(
builder2
});
.
build
()
.
webOnlyRootElement
);
test
(
'draw growing picture across frames clipped'
,
()
async
{
final
SurfaceSceneBuilder
builder
=
SurfaceSceneBuilder
();
await
matchGoldenFile
(
'canvas_draw_picture_acrossframes.png'
,
builder
.
pushClipRect
(
region:
region
);
const
Rect
.
fromLTRB
(
0
,
0
,
100
,
100
),
});
);
test
(
'draw growing picture across frames clipped'
,
()
async
{
_drawTestPicture
(
builder
,
100
,
true
);
final
SurfaceSceneBuilder
builder
=
SurfaceSceneBuilder
();
builder
.
pop
();
builder
.
pushClipRect
(
const
Rect
.
fromLTRB
(
0
,
0
,
100
,
100
),
html
.
Element
elm1
=
builder
.
build
().
webOnlyRootElement
;
);
html
.
document
.
body
.
append
(
elm1
);
_drawTestPicture
(
builder
,
100
,
true
);
// Now draw picture again but at larger size.
builder
.
pop
();
final
SurfaceSceneBuilder
builder2
=
SurfaceSceneBuilder
();
builder2
.
pushClipRect
(
html
.
Element
elm1
=
builder
const
Rect
.
fromLTRB
(
0
,
0
,
100
,
100
),
.
build
()
);
.
webOnlyRootElement
;
_drawTestPicture
(
builder2
,
20
,
true
);
html
.
document
.
body
.
append
(
elm1
);
builder2
.
pop
();
// Now draw picture again but at larger size.
final
SurfaceSceneBuilder
builder2
=
SurfaceSceneBuilder
();
builder2
.
pushClipRect
(
const
Rect
.
fromLTRB
(
0
,
0
,
100
,
100
),
);
_drawTestPicture
(
builder2
,
20
,
true
);
builder2
.
pop
();
elm1
.
remove
();
html
.
document
.
body
.
append
(
builder2
.
build
()
.
webOnlyRootElement
);
await
matchGoldenFile
(
'canvas_draw_picture_acrossframes_clipped.png'
,
region:
region
);
});
test
(
'PictureInPicture'
,
()
async
{
final
SurfaceSceneBuilder
builder
=
SurfaceSceneBuilder
();
final
Picture
greenRectPicture
=
_drawGreenRectIntoPicture
();
final
EnginePictureRecorder
recorder
=
PictureRecorder
();
final
RecordingCanvas
canvas
=
recorder
.
beginRecording
(
const
Rect
.
fromLTRB
(
0
,
0
,
100
,
100
));
canvas
.
drawPicture
(
greenRectPicture
);
builder
.
addPicture
(
Offset
(
10
,
10
),
recorder
.
endRecording
());
elm1
.
remove
();
html
.
Element
elm1
=
builder
html
.
document
.
body
.
append
(
builder2
.
build
().
webOnlyRootElement
);
.
build
()
.
webOnlyRootElement
;
html
.
document
.
body
.
append
(
elm1
);
await
matchGoldenFile
(
'canvas_draw_picture_acrossframes_clipped.png'
,
await
matchGoldenFile
(
'canvas_draw_picture_in_picture_rect.png'
,
region:
region
);
region:
region
);
});
});
});
}
}
...
@@ -110,6 +139,15 @@ void _drawTestPicture(SceneBuilder builder, double targetSize, bool clipped) {
...
@@ -110,6 +139,15 @@ void _drawTestPicture(SceneBuilder builder, double targetSize, bool clipped) {
);
);
}
}
Picture
_drawGreenRectIntoPicture
(
)
{
final
EnginePictureRecorder
recorder
=
PictureRecorder
();
final
RecordingCanvas
canvas
=
recorder
.
beginRecording
(
const
Rect
.
fromLTRB
(
0
,
0
,
100
,
100
));
canvas
.
drawRect
(
Rect
.
fromLTWH
(
20
,
20
,
50
,
50
),
Paint
()..
color
=
const
Color
(
0xFF00FF00
));
return
recorder
.
endRecording
();
}
typedef
PaintCallback
=
void
Function
(
RecordingCanvas
canvas
);
typedef
PaintCallback
=
void
Function
(
RecordingCanvas
canvas
);
const
String
_base64Encoded20x20TestImage
=
const
String
_base64Encoded20x20TestImage
=
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录