Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
weixin_43355755
engine
提交
5ba9ed51
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,发现更多精彩内容 >>
未验证
提交
5ba9ed51
编写于
8月 13, 2021
作者:
M
Mouad Debbar
提交者:
GitHub
8月 13, 2021
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[web] Clean up legacy Paragraph implementation (#28050)
上级
c388bfab
变更
19
展开全部
隐藏空白更改
内联
并排
Showing
19 changed file
with
104 addition
and
5597 deletion
+104
-5597
lib/web_ui/lib/src/engine/dom_renderer.dart
lib/web_ui/lib/src/engine/dom_renderer.dart
+0
-6
lib/web_ui/lib/src/engine/text/canvas_paragraph.dart
lib/web_ui/lib/src/engine/text/canvas_paragraph.dart
+6
-4
lib/web_ui/lib/src/engine/text/font_collection.dart
lib/web_ui/lib/src/engine/text/font_collection.dart
+0
-2
lib/web_ui/lib/src/engine/text/measurement.dart
lib/web_ui/lib/src/engine/text/measurement.dart
+0
-946
lib/web_ui/lib/src/engine/text/paragraph.dart
lib/web_ui/lib/src/engine/text/paragraph.dart
+0
-1027
lib/web_ui/lib/src/engine/text/ruler.dart
lib/web_ui/lib/src/engine/text/ruler.dart
+0
-722
lib/web_ui/lib/src/engine/web_experiments.dart
lib/web_ui/lib/src/engine/web_experiments.dart
+4
-42
lib/web_ui/lib/src/ui/text.dart
lib/web_ui/lib/src/ui/text.dart
+1
-5
lib/web_ui/test/engine/surface/scene_builder_test.dart
lib/web_ui/test/engine/surface/scene_builder_test.dart
+4
-1
lib/web_ui/test/engine/web_experiments_test.dart
lib/web_ui/test/engine/web_experiments_test.dart
+0
-67
lib/web_ui/test/html/compositing/compositing_golden_test.dart
...web_ui/test/html/compositing/compositing_golden_test.dart
+7
-5
lib/web_ui/test/html/paragraph/text_overflow_golden_test.dart
...web_ui/test/html/paragraph/text_overflow_golden_test.dart
+0
-103
lib/web_ui/test/html/paragraph/text_scuba.dart
lib/web_ui/test/html/paragraph/text_scuba.dart
+3
-33
lib/web_ui/test/html/paragraph/text_style_golden_test.dart
lib/web_ui/test/html/paragraph/text_style_golden_test.dart
+0
-248
lib/web_ui/test/paragraph_test.dart
lib/web_ui/test/paragraph_test.dart
+0
-1001
lib/web_ui/test/text/canvas_paragraph_test.dart
lib/web_ui/test/text/canvas_paragraph_test.dart
+50
-9
lib/web_ui/test/text/font_loading_test.dart
lib/web_ui/test/text/font_loading_test.dart
+0
-7
lib/web_ui/test/text/measurement_test.dart
lib/web_ui/test/text/measurement_test.dart
+0
-1181
lib/web_ui/test/text_test.dart
lib/web_ui/test/text_test.dart
+29
-188
未找到文件。
lib/web_ui/lib/src/engine/dom_renderer.dart
浏览文件 @
5ba9ed51
...
...
@@ -16,7 +16,6 @@ import 'keyboard_binding.dart';
import
'platform_dispatcher.dart'
;
import
'pointer_binding.dart'
;
import
'semantics.dart'
;
import
'text/measurement.dart'
;
import
'text_editing/text_editing.dart'
;
import
'util.dart'
;
import
'window.dart'
;
...
...
@@ -29,11 +28,6 @@ class DomRenderer {
reset
();
TextMeasurementService
.
initialize
(
rulerCacheCapacity:
10
,
root:
_glassPaneShadow
!.
node
,
);
assert
(()
{
_setupHotRestart
();
return
true
;
...
...
lib/web_ui/lib/src/engine/text/canvas_paragraph.dart
浏览文件 @
5ba9ed51
...
...
@@ -15,11 +15,13 @@ import 'paint_service.dart';
import
'paragraph.dart'
;
import
'word_breaker.dart'
;
const
ui
.
Color
_defaultTextColor
=
ui
.
Color
(
0xFFFF0000
);
/// A paragraph made up of a flat list of text spans and placeholders.
///
///
As opposed to [DomParagraph], a [CanvasParagraph] doesn't use a DOM element
///
to represent the structure of its spans and styles. Instead it uses a flat
///
list of [ParagraphSpan]
objects.
///
[CanvasParagraph] doesn't use a DOM element to represent the structure of
///
its spans and styles. Instead it uses a flat list of [ParagraphSpan]
/// objects.
class
CanvasParagraph
implements
EngineParagraph
{
/// This class is created by the engine, and should not be instantiated
/// or extended directly.
...
...
@@ -574,7 +576,7 @@ class RootStyleNode extends StyleNode {
final
EngineParagraphStyle
paragraphStyle
;
@override
final
ui
.
Color
_color
=
defaultTextColor
;
final
ui
.
Color
_color
=
_
defaultTextColor
;
@override
ui
.
TextDecoration
?
get
_decoration
=>
null
;
...
...
lib/web_ui/lib/src/engine/text/font_collection.dart
浏览文件 @
5ba9ed51
...
...
@@ -12,7 +12,6 @@ import '../assets.dart';
import
'../browser_detection.dart'
;
import
'../util.dart'
;
import
'layout_service.dart'
;
import
'measurement.dart'
;
const
String
ahemFontFamily
=
'Ahem'
;
const
String
ahemFontUrl
=
'packages/ui/assets/ahem.ttf'
;
...
...
@@ -215,7 +214,6 @@ class FontManager {
// There might be paragraph measurements for this new font before it is
// loaded. They were measured using fallback font, so we should clear the
// cache.
TextMeasurementService
.
clearCache
();
Spanometer
.
clearRulersCache
();
},
onError:
(
dynamic
exception
)
{
// Failures here will throw an html.DomException which confusingly
...
...
lib/web_ui/lib/src/engine/text/measurement.dart
浏览文件 @
5ba9ed51
此差异已折叠。
点击以展开。
lib/web_ui/lib/src/engine/text/paragraph.dart
浏览文件 @
5ba9ed51
此差异已折叠。
点击以展开。
lib/web_ui/lib/src/engine/text/ruler.dart
浏览文件 @
5ba9ed51
此差异已折叠。
点击以展开。
lib/web_ui/lib/src/engine/web_experiments.dart
浏览文件 @
5ba9ed51
...
...
@@ -19,53 +19,15 @@ class WebExperiments {
}
static
WebExperiments
ensureInitialized
()
{
return
WebExperiments
.
instance
??
(
WebExperiments
.
instance
=
WebExperiments
.
_
());
return
WebExperiments
.
instance
??
(
WebExperiments
.
instance
=
WebExperiments
.
_
());
}
static
WebExperiments
?
instance
;
/// Experiment flag for using canvas-based text measurement.
bool
get
useCanvasText
=>
_useCanvasText
;
set
useCanvasText
(
bool
?
enabled
)
{
_useCanvasText
=
enabled
??
_defaultUseCanvasText
;
}
static
const
bool
_defaultUseCanvasText
=
bool
.
fromEnvironment
(
'FLUTTER_WEB_USE_EXPERIMENTAL_CANVAS_TEXT'
,
defaultValue:
true
,
);
bool
_useCanvasText
=
_defaultUseCanvasText
;
// TODO(mdebbar): Clean up https://github.com/flutter/flutter/issues/71952
/// Experiment flag for using canvas-based measurement for rich text.
bool
get
useCanvasRichText
=>
_useCanvasRichText
;
set
useCanvasRichText
(
bool
?
enabled
)
{
_useCanvasRichText
=
enabled
??
_defaultUseCanvasRichText
;
}
static
const
bool
_defaultUseCanvasRichText
=
bool
.
fromEnvironment
(
'FLUTTER_WEB_USE_EXPERIMENTAL_CANVAS_RICH_TEXT'
,
defaultValue:
true
,
);
bool
_useCanvasRichText
=
_defaultUseCanvasRichText
;
/// Reset all experimental flags to their default values.
void
reset
()
{
_useCanvasText
=
_defaultUseCanvasText
;
_useCanvasRichText
=
_defaultUseCanvasRichText
;
}
void
reset
()
{}
/// Used to enable/disable experimental flags in the web engine.
void
updateExperiment
(
String
name
,
bool
?
enabled
)
{
switch
(
name
)
{
case
'useCanvasText'
:
useCanvasText
=
enabled
;
break
;
case
'useCanvasRichText'
:
useCanvasRichText
=
enabled
;
break
;
}
}
void
updateExperiment
(
String
name
,
bool
?
enabled
)
{}
}
lib/web_ui/lib/src/ui/text.dart
浏览文件 @
5ba9ed51
...
...
@@ -706,12 +706,8 @@ abstract class ParagraphBuilder {
factory
ParagraphBuilder
(
ParagraphStyle
style
)
{
if
(
engine
.
useCanvasKit
)
{
return
engine
.
CkParagraphBuilder
(
style
);
}
else
if
(
engine
.
WebExperiments
.
instance
!.
useCanvasRichText
)
{
return
engine
.
CanvasParagraphBuilder
(
style
as
engine
.
EngineParagraphStyle
);
}
else
{
return
engine
.
DomParagraphBuilder
(
style
as
engine
.
EngineParagraphStyle
);
}
return
engine
.
CanvasParagraphBuilder
(
style
as
engine
.
EngineParagraphStyle
);
}
void
pushStyle
(
TextStyle
style
);
void
pop
();
...
...
lib/web_ui/test/engine/surface/scene_builder_test.dart
浏览文件 @
5ba9ed51
...
...
@@ -468,7 +468,10 @@ void testMain() {
final
bool
useOffset
=
int
.
tryParse
(
char
)
==
null
;
final
EnginePictureRecorder
recorder
=
EnginePictureRecorder
();
final
RecordingCanvas
canvas
=
recorder
.
beginRecording
(
const
ui
.
Rect
.
fromLTRB
(
0
,
0
,
400
,
400
));
final
DomParagraph
paragraph
=
(
DomParagraphBuilder
(
EngineParagraphStyle
())..
addText
(
char
)).
build
()
as
DomParagraph
;
final
ui
.
Paragraph
paragraph
=
(
ui
.
ParagraphBuilder
(
ui
.
ParagraphStyle
())
..
pushStyle
(
ui
.
TextStyle
(
decoration:
ui
.
TextDecoration
.
lineThrough
))
..
addText
(
char
))
.
build
();
paragraph
.
layout
(
const
ui
.
ParagraphConstraints
(
width:
1000
));
canvas
.
drawParagraph
(
paragraph
,
ui
.
Offset
.
zero
);
final
ui
.
EngineLayer
newLayer
=
useOffset
...
...
lib/web_ui/test/engine/web_experiments_test.dart
浏览文件 @
5ba9ed51
...
...
@@ -9,9 +9,6 @@ import 'package:test/bootstrap/browser.dart';
import
'package:test/test.dart'
;
import
'package:ui/src/engine/web_experiments.dart'
;
const
bool
_defaultUseCanvasText
=
true
;
const
bool
_defaultUseCanvasRichText
=
true
;
void
main
(
)
{
internalBootstrapBrowserTest
(()
=>
testMain
);
}
...
...
@@ -25,70 +22,6 @@ void testMain() {
WebExperiments
.
instance
!.
reset
();
});
test
(
'default web experiment values'
,
()
{
expect
(
WebExperiments
.
instance
!.
useCanvasText
,
_defaultUseCanvasText
);
expect
(
WebExperiments
.
instance
!.
useCanvasRichText
,
_defaultUseCanvasRichText
);
});
test
(
'can turn on/off web experiments'
,
()
{
WebExperiments
.
instance
!.
updateExperiment
(
'useCanvasText'
,
true
);
WebExperiments
.
instance
!.
updateExperiment
(
'useCanvasRichText'
,
true
);
expect
(
WebExperiments
.
instance
!.
useCanvasText
,
isTrue
);
expect
(
WebExperiments
.
instance
!.
useCanvasRichText
,
isTrue
);
WebExperiments
.
instance
!.
updateExperiment
(
'useCanvasText'
,
false
);
WebExperiments
.
instance
!.
updateExperiment
(
'useCanvasRichText'
,
false
);
expect
(
WebExperiments
.
instance
!.
useCanvasText
,
isFalse
);
expect
(
WebExperiments
.
instance
!.
useCanvasRichText
,
isFalse
);
WebExperiments
.
instance
!.
updateExperiment
(
'useCanvasText'
,
null
);
WebExperiments
.
instance
!.
updateExperiment
(
'useCanvasRichText'
,
null
);
// Goes back to default value.
expect
(
WebExperiments
.
instance
!.
useCanvasText
,
_defaultUseCanvasText
);
expect
(
WebExperiments
.
instance
!.
useCanvasRichText
,
_defaultUseCanvasRichText
);
});
test
(
'ignores unknown experiments'
,
()
{
expect
(
WebExperiments
.
instance
!.
useCanvasText
,
_defaultUseCanvasText
);
expect
(
WebExperiments
.
instance
!.
useCanvasRichText
,
_defaultUseCanvasRichText
);
WebExperiments
.
instance
!.
updateExperiment
(
'foobarbazqux'
,
true
);
expect
(
WebExperiments
.
instance
!.
useCanvasText
,
_defaultUseCanvasText
);
expect
(
WebExperiments
.
instance
!.
useCanvasRichText
,
_defaultUseCanvasRichText
);
WebExperiments
.
instance
!.
updateExperiment
(
'foobarbazqux'
,
false
);
expect
(
WebExperiments
.
instance
!.
useCanvasText
,
_defaultUseCanvasText
);
expect
(
WebExperiments
.
instance
!.
useCanvasRichText
,
_defaultUseCanvasRichText
);
});
test
(
'can reset web experiments'
,
()
{
WebExperiments
.
instance
!.
updateExperiment
(
'useCanvasText'
,
false
);
WebExperiments
.
instance
!.
updateExperiment
(
'useCanvasRichText'
,
false
);
WebExperiments
.
instance
!.
reset
();
expect
(
WebExperiments
.
instance
!.
useCanvasText
,
_defaultUseCanvasText
);
expect
(
WebExperiments
.
instance
!.
useCanvasRichText
,
_defaultUseCanvasRichText
);
WebExperiments
.
instance
!.
updateExperiment
(
'useCanvasText'
,
false
);
WebExperiments
.
instance
!.
updateExperiment
(
'useCanvasRichText'
,
false
);
WebExperiments
.
instance
!.
updateExperiment
(
'foobarbazqux'
,
true
);
WebExperiments
.
instance
!.
reset
();
expect
(
WebExperiments
.
instance
!.
useCanvasText
,
_defaultUseCanvasText
);
expect
(
WebExperiments
.
instance
!.
useCanvasRichText
,
_defaultUseCanvasRichText
);
});
test
(
'js interop also works'
,
()
{
expect
(
WebExperiments
.
instance
!.
useCanvasText
,
_defaultUseCanvasText
);
expect
(
WebExperiments
.
instance
!.
useCanvasRichText
,
_defaultUseCanvasRichText
);
expect
(()
=>
jsUpdateExperiment
(
'useCanvasText'
,
true
),
returnsNormally
);
expect
(()
=>
jsUpdateExperiment
(
'useCanvasRichText'
,
true
),
returnsNormally
);
expect
(
WebExperiments
.
instance
!.
useCanvasText
,
isTrue
);
expect
(
WebExperiments
.
instance
!.
useCanvasRichText
,
isTrue
);
expect
(()
=>
jsUpdateExperiment
(
'useCanvasText'
,
null
),
returnsNormally
);
expect
(()
=>
jsUpdateExperiment
(
'useCanvasRichText'
,
null
),
returnsNormally
);
expect
(
WebExperiments
.
instance
!.
useCanvasText
,
_defaultUseCanvasText
);
expect
(
WebExperiments
.
instance
!.
useCanvasRichText
,
_defaultUseCanvasRichText
);
});
test
(
'js interop throws on wrong type'
,
()
{
expect
(()
=>
jsUpdateExperiment
(
123
,
true
),
throwsA
(
anything
));
expect
(()
=>
jsUpdateExperiment
(
'foo'
,
123
),
throwsA
(
anything
));
...
...
lib/web_ui/test/html/compositing/compositing_golden_test.dart
浏览文件 @
5ba9ed51
...
...
@@ -818,10 +818,12 @@ void _testCullRectComputation() {
'renders clipped text with high quality'
,
()
async
{
// To reproduce blurriness we need real clipping.
final
DomParagraph
paragraph
=
(
DomParagraphBuilder
(
EngineParagraphStyle
(
fontFamily:
'Roboto'
))
final
CanvasParagraph
paragraph
=
(
ui
.
ParagraphBuilder
(
ui
.
ParagraphStyle
(
fontFamily:
'Roboto'
))
// Use a decoration to force rendering in DOM mode.
..
pushStyle
(
ui
.
TextStyle
(
decoration:
ui
.
TextDecoration
.
lineThrough
,
decorationColor:
const
ui
.
Color
(
0x00000000
)))
..
addText
(
'Am I blurry?'
))
.
build
()
as
Dom
Paragraph
;
.
build
()
as
Canvas
Paragraph
;
paragraph
.
layout
(
const
ui
.
ParagraphConstraints
(
width:
1000
));
final
ui
.
Rect
canvasSize
=
ui
.
Rect
.
fromLTRB
(
...
...
@@ -843,7 +845,7 @@ void _testCullRectComputation() {
final
RecordingCanvas
canvas
=
recorder
.
beginRecording
(
outerClip
);
canvas
.
drawParagraph
(
paragraph
,
const
ui
.
Offset
(
8.5
,
8.5
));
final
ui
.
Picture
picture
=
recorder
.
endRecording
();
expect
(
canvas
.
renderStrategy
.
hasArbitraryPaint
,
isFalse
);
expect
(
paragraph
.
drawOnCanvas
,
isFalse
);
builder
.
addPicture
(
ui
.
Offset
.
zero
,
...
...
@@ -857,7 +859,7 @@ void _testCullRectComputation() {
final
RecordingCanvas
canvas
=
recorder
.
beginRecording
(
innerClip
);
canvas
.
drawParagraph
(
paragraph
,
ui
.
Offset
(
8.5
,
8.5
+
innerClip
.
top
));
final
ui
.
Picture
picture
=
recorder
.
endRecording
();
expect
(
canvas
.
renderStrategy
.
hasArbitraryPaint
,
isFalse
);
expect
(
paragraph
.
drawOnCanvas
,
isFalse
);
builder
.
addPicture
(
ui
.
Offset
.
zero
,
...
...
lib/web_ui/test/html/paragraph/text_overflow_golden_test.dart
浏览文件 @
5ba9ed51
...
...
@@ -13,10 +13,6 @@ import 'text_scuba.dart';
typedef
CanvasTest
=
FutureOr
<
void
>
Function
(
EngineCanvas
canvas
);
const
String
threeLines
=
'First
\n
Second
\n
Third'
;
const
String
veryLongWithShortPrefix
=
'Lorem ipsum dolor
\n
sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.'
;
const
String
veryLongWithShortSuffix
=
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et
\n
dolore magna aliqua.'
;
const
String
veryLong
=
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.'
;
const
String
longUnbreakable
=
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
;
...
...
@@ -30,18 +26,8 @@ Future<void> testMain() async {
viewportSize:
const
Size
(
800
,
800
),
);
final
TextStyle
warningStyle
=
TextStyle
(
color:
const
Color
(
0xFFFF0000
),
fontFamily:
'Roboto'
,
fontSize:
10
,
);
setUpStableTestFonts
();
EngineParagraph
warning
(
String
text
)
{
return
paragraph
(
text
,
textStyle:
warningStyle
);
}
testEachCanvas
(
'maxLines clipping'
,
(
EngineCanvas
canvas
)
{
Offset
offset
=
Offset
.
zero
;
EngineParagraph
p
;
...
...
@@ -69,93 +55,4 @@ Future<void> testMain() async {
return
scuba
.
diffCanvasScreenshot
(
canvas
,
'text_max_lines'
);
});
testEachCanvas
(
'maxLines with overflow'
,
(
EngineCanvas
canvas
)
{
Offset
offset
=
Offset
.
zero
;
EngineParagraph
p
;
// Only the first line is rendered with no ellipsis because the first line
// doesn't overflow.
p
=
paragraph
(
threeLines
,
paragraphStyle:
ParagraphStyle
(
ellipsis:
'...'
),
);
canvas
.
drawParagraph
(
p
,
offset
);
offset
=
offset
.
translate
(
0
,
p
.
height
+
10
);
// The first two lines are rendered with an ellipsis on the 2nd line.
p
=
paragraph
(
veryLongWithShortPrefix
,
paragraphStyle:
ParagraphStyle
(
ellipsis:
'...'
),
maxWidth:
200
,
);
canvas
.
drawParagraph
(
p
,
offset
);
offset
=
offset
.
translate
(
0
,
p
.
height
+
10
);
// Only the first line is rendered with an ellipsis.
if
(!
WebExperiments
.
instance
!.
useCanvasText
)
{
// This is now correct with the canvas-based measurement, so we shouldn't
// print the "(wrong)" warning.
p
=
warning
(
'(wrong)'
);
canvas
.
drawParagraph
(
p
,
offset
);
offset
=
offset
.
translate
(
0
,
p
.
height
);
}
p
=
paragraph
(
veryLongWithShortSuffix
,
paragraphStyle:
ParagraphStyle
(
ellipsis:
'...'
),
maxWidth:
200
,
);
canvas
.
drawParagraph
(
p
,
offset
);
offset
=
offset
.
translate
(
0
,
p
.
height
+
10
);
// Only the first two lines are rendered and the ellipsis appears on the 2nd
// line.
if
(!
WebExperiments
.
instance
!.
useCanvasText
)
{
// This is now correct with the canvas-based measurement, so we shouldn't
// print the "(wrong)" warning.
p
=
warning
(
'(wrong)'
);
canvas
.
drawParagraph
(
p
,
offset
);
offset
=
offset
.
translate
(
0
,
p
.
height
);
}
p
=
paragraph
(
veryLong
,
paragraphStyle:
ParagraphStyle
(
maxLines:
2
,
ellipsis:
'...'
),
maxWidth:
200
,
);
canvas
.
drawParagraph
(
p
,
offset
);
offset
=
offset
.
translate
(
0
,
p
.
height
+
10
);
return
scuba
.
diffCanvasScreenshot
(
canvas
,
'text_max_lines_with_ellipsis'
);
});
testEachCanvas
(
'long unbreakable text'
,
(
EngineCanvas
canvas
)
{
Offset
offset
=
Offset
.
zero
;
EngineParagraph
p
;
// The whole line is rendered unbroken when there are no constraints.
p
=
paragraph
(
longUnbreakable
);
canvas
.
drawParagraph
(
p
,
offset
);
offset
=
offset
.
translate
(
0
,
p
.
height
+
10
);
// The whole line is rendered with an ellipsis.
p
=
paragraph
(
longUnbreakable
,
paragraphStyle:
ParagraphStyle
(
ellipsis:
'...'
),
maxWidth:
200
,
);
canvas
.
drawParagraph
(
p
,
offset
);
offset
=
offset
.
translate
(
0
,
p
.
height
+
10
);
// The text is broken into multiple lines.
p
=
paragraph
(
longUnbreakable
,
maxWidth:
200
);
canvas
.
drawParagraph
(
p
,
offset
);
offset
=
offset
.
translate
(
0
,
p
.
height
+
10
);
// Very narrow constraint (less than one character's width).
p
=
paragraph
(
'AA'
,
maxWidth:
7
);
canvas
.
drawParagraph
(
p
,
offset
);
offset
=
offset
.
translate
(
0
,
p
.
height
+
10
);
return
scuba
.
diffCanvasScreenshot
(
canvas
,
'text_long_unbreakable'
);
});
}
lib/web_ui/test/html/paragraph/text_scuba.dart
浏览文件 @
5ba9ed51
...
...
@@ -71,7 +71,7 @@ class EngineScubaTester {
sceneElement
.
append
(
canvas
.
rootElement
);
html
.
document
.
body
!.
append
(
sceneElement
);
String
screenshotName
=
'
${fileName}
_
${canvas.runtimeType}
'
;
if
(
WebExperiments
.
instance
!.
useCanvasText
)
{
if
(
canvas
is
BitmapCanvas
)
{
screenshotName
+=
'+canvas_measurement'
;
}
await
diffScreenshot
(
...
...
@@ -94,41 +94,11 @@ typedef CanvasTest = FutureOr<void> Function(EngineCanvas canvas);
void
testEachCanvas
(
String
description
,
CanvasTest
body
,
{
double
?
maxDiffRate
})
{
const
ui
.
Rect
bounds
=
ui
.
Rect
.
fromLTWH
(
0
,
0
,
600
,
800
);
test
(
'
$description
(bitmap)'
,
()
{
try
{
TextMeasurementService
.
initialize
(
rulerCacheCapacity:
2
);
WebExperiments
.
instance
!.
useCanvasText
=
false
;
WebExperiments
.
instance
!.
useCanvasRichText
=
false
;
return
body
(
BitmapCanvas
(
bounds
,
RenderStrategy
()));
}
finally
{
WebExperiments
.
instance
!.
useCanvasText
=
null
;
WebExperiments
.
instance
!.
useCanvasRichText
=
null
;
TextMeasurementService
.
clearCache
();
}
});
test
(
'
$description
(bitmap + canvas measurement)'
,
()
async
{
try
{
TextMeasurementService
.
initialize
(
rulerCacheCapacity:
2
);
WebExperiments
.
instance
!.
useCanvasText
=
true
;
WebExperiments
.
instance
!.
useCanvasRichText
=
false
;
await
body
(
BitmapCanvas
(
bounds
,
RenderStrategy
()));
}
finally
{
WebExperiments
.
instance
!.
useCanvasText
=
null
;
WebExperiments
.
instance
!.
useCanvasRichText
=
null
;
TextMeasurementService
.
clearCache
();
}
return
body
(
BitmapCanvas
(
bounds
,
RenderStrategy
()));
});
test
(
'
$description
(dom)'
,
()
{
try
{
TextMeasurementService
.
initialize
(
rulerCacheCapacity:
2
);
WebExperiments
.
instance
!.
useCanvasText
=
false
;
WebExperiments
.
instance
!.
useCanvasRichText
=
false
;
return
body
(
DomCanvas
(
domRenderer
.
createElement
(
'flt-picture'
)));
}
finally
{
WebExperiments
.
instance
!.
useCanvasText
=
null
;
WebExperiments
.
instance
!.
useCanvasRichText
=
null
;
TextMeasurementService
.
clearCache
();
}
return
body
(
DomCanvas
(
domRenderer
.
createElement
(
'flt-picture'
)));
});
}
...
...
lib/web_ui/test/html/paragraph/text_style_golden_test.dart
已删除
100644 → 0
浏览文件 @
c388bfab
// 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
'package:test/bootstrap/browser.dart'
;
import
'package:ui/src/engine.dart'
;
import
'package:ui/ui.dart'
;
import
'text_scuba.dart'
;
void
main
(
)
{
internalBootstrapBrowserTest
(()
=>
testMain
);
}
Future
<
void
>
testMain
()
async
{
final
EngineScubaTester
scuba
=
await
EngineScubaTester
.
initialize
(
viewportSize:
const
Size
(
800
,
800
),
);
setUpStableTestFonts
();
void
drawLetterAndWordSpacing
(
EngineCanvas
canvas
)
{
Offset
offset
=
Offset
.
zero
;
for
(
double
spacing
=
0
;
spacing
<
15
;
spacing
+=
5
)
{
canvas
.
drawParagraph
(
paragraph
(
'HelloWorld'
,
textStyle:
TextStyle
(
color:
const
Color
(
0xFF000000
),
decoration:
TextDecoration
.
none
,
fontFamily:
'Roboto'
,
fontSize:
30
,
letterSpacing:
spacing
)),
offset
,
);
offset
=
offset
.
translate
(
0
,
40
);
}
for
(
double
spacing
=
0
;
spacing
<
30
;
spacing
+=
10
)
{
final
TextStyle
textStyle
=
TextStyle
(
color:
const
Color
(
0xFF00FF00
),
decoration:
TextDecoration
.
none
,
fontFamily:
'Roboto'
,
fontSize:
30
,
wordSpacing:
spacing
);
canvas
.
drawParagraph
(
paragraph
(
'Hello World'
,
textStyle:
textStyle
,
maxWidth:
600
),
offset
,
);
offset
=
offset
.
translate
(
0
,
40
);
}
}
testEachCanvas
(
'draws text with letter/word spacing'
,
(
EngineCanvas
canvas
)
{
drawLetterAndWordSpacing
(
canvas
);
return
scuba
.
diffCanvasScreenshot
(
canvas
,
'paint_bounds_for_text_style_letter_spacing'
);
});
void
drawTextDecorationStyle
(
EngineCanvas
canvas
)
{
final
List
<
TextDecorationStyle
>
decorationStyles
=
<
TextDecorationStyle
>[
TextDecorationStyle
.
solid
,
TextDecorationStyle
.
double
,
TextDecorationStyle
.
dotted
,
TextDecorationStyle
.
dashed
,
TextDecorationStyle
.
wavy
,
];
Offset
offset
=
Offset
.
zero
;
for
(
final
TextDecorationStyle
decorationStyle
in
decorationStyles
)
{
final
TextStyle
textStyle
=
TextStyle
(
color:
const
Color
.
fromRGBO
(
50
,
50
,
255
,
1.0
),
decoration:
TextDecoration
.
underline
,
decorationStyle:
decorationStyle
,
decorationColor:
const
Color
.
fromRGBO
(
50
,
50
,
50
,
1.0
),
fontFamily:
'Roboto'
,
fontSize:
30
,
);
canvas
.
drawParagraph
(
paragraph
(
'Hello World'
,
textStyle:
textStyle
,
maxWidth:
600
),
offset
,
);
offset
=
offset
.
translate
(
0
,
40
);
}
}
testEachCanvas
(
'draws text decoration style'
,
(
EngineCanvas
canvas
)
{
drawTextDecorationStyle
(
canvas
);
return
scuba
.
diffCanvasScreenshot
(
canvas
,
'paint_bounds_for_text_decorationStyle'
);
});
void
drawTextDecoration
(
EngineCanvas
canvas
)
{
final
List
<
TextDecoration
>
decorations
=
<
TextDecoration
>[
TextDecoration
.
overline
,
TextDecoration
.
underline
,
TextDecoration
.
combine
(<
TextDecoration
>[
TextDecoration
.
underline
,
TextDecoration
.
lineThrough
]),
TextDecoration
.
combine
(
<
TextDecoration
>[
TextDecoration
.
underline
,
TextDecoration
.
overline
]),
TextDecoration
.
combine
(
<
TextDecoration
>[
TextDecoration
.
overline
,
TextDecoration
.
lineThrough
])
];
Offset
offset
=
Offset
.
zero
;
for
(
final
TextDecoration
decoration
in
decorations
)
{
final
TextStyle
textStyle
=
TextStyle
(
color:
const
Color
.
fromRGBO
(
50
,
50
,
255
,
1.0
),
decoration:
decoration
,
decorationStyle:
TextDecorationStyle
.
solid
,
decorationColor:
const
Color
.
fromRGBO
(
255
,
160
,
0
,
1.0
),
fontFamily:
'Roboto'
,
fontSize:
20
,
);
canvas
.
drawParagraph
(
paragraph
(
'Hello World
$decoration
'
,
textStyle:
textStyle
,
maxWidth:
600
,
),
offset
,
);
offset
=
offset
.
translate
(
0
,
40
);
}
}
testEachCanvas
(
'draws text decoration'
,
(
EngineCanvas
canvas
)
{
drawTextDecoration
(
canvas
);
return
scuba
.
diffCanvasScreenshot
(
canvas
,
'paint_bounds_for_text_decoration'
);
});
void
drawTextWithBackground
(
EngineCanvas
canvas
)
{
// Single-line text.
canvas
.
drawParagraph
(
paragraph
(
'Hello World'
,
maxWidth:
600
,
textStyle:
TextStyle
(
color:
const
Color
.
fromRGBO
(
0
,
0
,
0
,
1.0
),
background:
Paint
()..
color
=
const
Color
.
fromRGBO
(
255
,
50
,
50
,
1.0
),
fontFamily:
'Roboto'
,
fontSize:
30
,
),
),
Offset
.
zero
,
);
// Multi-line text.
canvas
.
drawParagraph
(
paragraph
(
'Multi line Hello World paragraph'
,
maxWidth:
200
,
textStyle:
TextStyle
(
color:
const
Color
.
fromRGBO
(
0
,
0
,
0
,
1.0
),
background:
Paint
()..
color
=
const
Color
.
fromRGBO
(
50
,
50
,
255
,
1.0
),
fontFamily:
'Roboto'
,
fontSize:
30
,
),
),
const
Offset
(
0
,
40
),
);
}
void
drawTextWithShadow
(
EngineCanvas
canvas
)
{
// Single-line text.
canvas
.
drawParagraph
(
paragraph
(
'Hello World'
,
maxWidth:
600
,
textStyle:
TextStyle
(
color:
const
Color
.
fromRGBO
(
0
,
0
,
0
,
1.0
),
background:
Paint
()..
color
=
const
Color
.
fromRGBO
(
255
,
50
,
50
,
1.0
),
fontFamily:
'Roboto'
,
fontSize:
30
,
shadows:
<
Shadow
>[
const
Shadow
(
blurRadius:
0
,
color:
Color
.
fromRGBO
(
255
,
0
,
255
,
1.0
),
offset:
Offset
(
10
,
5
),
),
],
),
),
Offset
.
zero
,
);
// Multi-line text.
canvas
.
drawParagraph
(
paragraph
(
'Multi line Hello World paragraph'
,
maxWidth:
200
,
textStyle:
TextStyle
(
color:
const
Color
.
fromRGBO
(
0
,
0
,
0
,
1.0
),
background:
Paint
()..
color
=
const
Color
.
fromRGBO
(
50
,
50
,
255
,
1.0
),
fontFamily:
'Roboto'
,
fontSize:
30
,
shadows:
<
Shadow
>[
const
Shadow
(
blurRadius:
0
,
color:
Color
.
fromRGBO
(
255
,
0
,
255
,
1.0
),
offset:
Offset
(
10
,
5
),
),
const
Shadow
(
blurRadius:
0
,
color:
Color
.
fromRGBO
(
0
,
255
,
255
,
1.0
),
offset:
Offset
(-
10
,
-
5
),
),
],
),
),
const
Offset
(
0
,
40
),
);
}
testEachCanvas
(
'draws text with a background'
,
(
EngineCanvas
canvas
)
{
drawTextWithBackground
(
canvas
);
return
scuba
.
diffCanvasScreenshot
(
canvas
,
'text_background'
);
});
testEachCanvas
(
'draws text with a shadow'
,
(
EngineCanvas
canvas
)
{
drawTextWithShadow
(
canvas
);
return
scuba
.
diffCanvasScreenshot
(
canvas
,
'text_shadow'
,
maxDiffRatePercent:
0.2
);
});
testEachCanvas
(
'Handles disabled strut style'
,
(
EngineCanvas
canvas
)
{
// Flutter uses [StrutStyle.disabled] for the [SelectableText] widget. This
// translates into a strut style with a [height] of 0, which wasn't being
// handled correctly by the web engine.
final
StrutStyle
disabled
=
StrutStyle
(
height:
0
,
leading:
0
);
canvas
.
drawParagraph
(
paragraph
(
'Hello
\n
World'
,
paragraphStyle:
ParagraphStyle
(
strutStyle:
disabled
),
),
Offset
.
zero
,
);
return
scuba
.
diffCanvasScreenshot
(
canvas
,
'text_strut_style_disabled'
,
region:
const
Rect
.
fromLTRB
(
0
,
0
,
100
,
100
),
maxDiffRatePercent:
0.0
,
);
});
}
lib/web_ui/test/paragraph_test.dart
已删除
100644 → 0
浏览文件 @
c388bfab
此差异已折叠。
点击以展开。
lib/web_ui/test/text/canvas_paragraph_test.dart
浏览文件 @
5ba9ed51
...
...
@@ -7,6 +7,8 @@ import 'package:test/test.dart';
import
'package:ui/src/engine.dart'
;
import
'package:ui/ui.dart'
as
ui
;
import
'../html/paragraph/helper.dart'
;
const
ui
.
Color
white
=
ui
.
Color
(
0xFFFFFFFF
);
const
ui
.
Color
black
=
ui
.
Color
(
0xFF000000
);
const
ui
.
Color
red
=
ui
.
Color
(
0xFFFF0000
);
...
...
@@ -22,15 +24,6 @@ ui.ParagraphConstraints constrain(double width) {
return
ui
.
ParagraphConstraints
(
width:
width
);
}
CanvasParagraph
rich
(
EngineParagraphStyle
style
,
void
Function
(
CanvasParagraphBuilder
)
callback
,
)
{
final
CanvasParagraphBuilder
builder
=
CanvasParagraphBuilder
(
style
);
callback
(
builder
);
return
builder
.
build
();
}
void
main
(
)
{
internalBootstrapBrowserTest
(()
=>
testMain
);
}
...
...
@@ -686,6 +679,54 @@ Future<void> testMain() async {
}
});
});
test
(
'
$CanvasParagraph
.getWordBoundary'
,
()
{
final
ui
.
Paragraph
paragraph
=
plain
(
ahemStyle
,
'Lorem ipsum dolor'
);
const
ui
.
TextRange
loremRange
=
ui
.
TextRange
(
start:
0
,
end:
5
);
expect
(
paragraph
.
getWordBoundary
(
const
ui
.
TextPosition
(
offset:
0
)),
loremRange
);
expect
(
paragraph
.
getWordBoundary
(
const
ui
.
TextPosition
(
offset:
1
)),
loremRange
);
expect
(
paragraph
.
getWordBoundary
(
const
ui
.
TextPosition
(
offset:
2
)),
loremRange
);
expect
(
paragraph
.
getWordBoundary
(
const
ui
.
TextPosition
(
offset:
3
)),
loremRange
);
expect
(
paragraph
.
getWordBoundary
(
const
ui
.
TextPosition
(
offset:
4
)),
loremRange
);
const
ui
.
TextRange
firstSpace
=
ui
.
TextRange
(
start:
5
,
end:
6
);
expect
(
paragraph
.
getWordBoundary
(
const
ui
.
TextPosition
(
offset:
5
)),
firstSpace
);
const
ui
.
TextRange
ipsumRange
=
ui
.
TextRange
(
start:
6
,
end:
11
);
expect
(
paragraph
.
getWordBoundary
(
const
ui
.
TextPosition
(
offset:
6
)),
ipsumRange
);
expect
(
paragraph
.
getWordBoundary
(
const
ui
.
TextPosition
(
offset:
7
)),
ipsumRange
);
expect
(
paragraph
.
getWordBoundary
(
const
ui
.
TextPosition
(
offset:
8
)),
ipsumRange
);
expect
(
paragraph
.
getWordBoundary
(
const
ui
.
TextPosition
(
offset:
9
)),
ipsumRange
);
expect
(
paragraph
.
getWordBoundary
(
const
ui
.
TextPosition
(
offset:
10
)),
ipsumRange
);
const
ui
.
TextRange
secondSpace
=
ui
.
TextRange
(
start:
11
,
end:
12
);
expect
(
paragraph
.
getWordBoundary
(
const
ui
.
TextPosition
(
offset:
11
)),
secondSpace
);
const
ui
.
TextRange
dolorRange
=
ui
.
TextRange
(
start:
12
,
end:
17
);
expect
(
paragraph
.
getWordBoundary
(
const
ui
.
TextPosition
(
offset:
12
)),
dolorRange
);
expect
(
paragraph
.
getWordBoundary
(
const
ui
.
TextPosition
(
offset:
13
)),
dolorRange
);
expect
(
paragraph
.
getWordBoundary
(
const
ui
.
TextPosition
(
offset:
14
)),
dolorRange
);
expect
(
paragraph
.
getWordBoundary
(
const
ui
.
TextPosition
(
offset:
15
)),
dolorRange
);
expect
(
paragraph
.
getWordBoundary
(
const
ui
.
TextPosition
(
offset:
16
)),
dolorRange
);
const
ui
.
TextRange
endRange
=
ui
.
TextRange
(
start:
17
,
end:
17
);
expect
(
paragraph
.
getWordBoundary
(
const
ui
.
TextPosition
(
offset:
17
)),
endRange
);
});
test
(
'
$CanvasParagraph
.longestLine'
,
()
{
final
ui
.
Paragraph
paragraph
=
plain
(
ahemStyle
,
'abcd
\n
abcde abc'
);
paragraph
.
layout
(
const
ui
.
ParagraphConstraints
(
width:
80.0
));
expect
(
paragraph
.
longestLine
,
50.0
);
});
test
(
'
$CanvasParagraph
.width should be a whole integer'
,
()
{
final
ui
.
Paragraph
paragraph
=
plain
(
ahemStyle
,
'abc'
);
paragraph
.
layout
(
const
ui
.
ParagraphConstraints
(
width:
30.8
));
expect
(
paragraph
.
width
,
30
);
expect
(
paragraph
.
height
,
10
);
});
}
/// Shortcut to create a [ui.TextBox] with an optional [ui.TextDirection].
...
...
lib/web_ui/test/text/font_loading_test.dart
浏览文件 @
5ba9ed51
...
...
@@ -56,12 +56,6 @@ Future<void> testMain() async {
const
ui
.
ParagraphConstraints
constraints
=
ui
.
ParagraphConstraints
(
width:
30.0
);
final
DomParagraphBuilder
domBuilder
=
DomParagraphBuilder
(
style
);
domBuilder
.
addText
(
'test'
);
// Triggers the measuring and verifies the result has been cached.
domBuilder
.
build
().
layout
(
constraints
);
expect
(
TextMeasurementService
.
rulerManager
!.
rulers
.
length
,
1
);
final
CanvasParagraphBuilder
canvasBuilder
=
CanvasParagraphBuilder
(
style
);
canvasBuilder
.
addText
(
'test'
);
// Triggers the measuring and verifies the ruler cache has been populated.
...
...
@@ -78,7 +72,6 @@ Future<void> testMain() async {
// Verifies the font is loaded, and the cache is cleaned.
expect
(
_containsFontFamily
(
'Blehm'
),
isTrue
);
expect
(
TextMeasurementService
.
rulerManager
!.
rulers
.
length
,
0
);
expect
(
Spanometer
.
rulers
.
length
,
0
);
},
// TODO(hterkelsen): https://github.com/flutter/flutter/issues/56702
...
...
lib/web_ui/test/text/measurement_test.dart
已删除
100644 → 0
浏览文件 @
c388bfab
此差异已折叠。
点击以展开。
lib/web_ui/test/text_test.dart
浏览文件 @
5ba9ed51
...
...
@@ -10,6 +10,7 @@ import 'package:test/test.dart';
import
'package:ui/src/engine.dart'
;
import
'package:ui/ui.dart'
;
import
'html/paragraph/helper.dart'
;
import
'matchers.dart'
;
void
main
(
)
{
...
...
@@ -88,16 +89,13 @@ Future<void> testMain() async {
});
test
(
'lay out unattached paragraph'
,
()
{
final
DomParagraphBuilder
builder
=
DomParagraphBuilder
(
EngineParagraphStyle
(
final
CanvasParagraph
paragraph
=
plain
(
EngineParagraphStyle
(
fontFamily:
'sans-serif'
,
fontStyle:
FontStyle
.
normal
,
fontWeight:
FontWeight
.
normal
,
fontSize:
14.0
,
));
builder
.
addText
(
'How do you do this fine morning?'
);
final
DomParagraph
paragraph
=
builder
.
build
()
as
DomParagraph
;
),
'How do you do this fine morning?'
);
expect
(
paragraph
.
paragraphElement
.
parent
,
isNull
);
expect
(
paragraph
.
height
,
0.0
);
expect
(
paragraph
.
width
,
-
1.0
);
expect
(
paragraph
.
minIntrinsicWidth
,
0.0
);
...
...
@@ -107,7 +105,6 @@ Future<void> testMain() async {
paragraph
.
layout
(
const
ParagraphConstraints
(
width:
60.0
));
expect
(
paragraph
.
paragraphElement
.
parent
,
isNull
);
expect
(
paragraph
.
height
,
greaterThan
(
0.0
));
expect
(
paragraph
.
width
,
greaterThan
(
0.0
));
expect
(
paragraph
.
minIntrinsicWidth
,
greaterThan
(
0.0
));
...
...
@@ -154,18 +151,18 @@ Future<void> testMain() async {
});
test
(
'
$ParagraphBuilder
detects plain text'
,
()
{
DomParagraphBuilder
builder
=
Dom
ParagraphBuilder
(
EngineParagraphStyle
(
ParagraphBuilder
builder
=
ParagraphBuilder
(
EngineParagraphStyle
(
fontFamily:
'sans-serif'
,
fontStyle:
FontStyle
.
normal
,
fontWeight:
FontWeight
.
normal
,
fontSize:
15.0
,
));
builder
.
addText
(
'hi'
);
DomParagraph
paragraph
=
builder
.
build
()
as
Dom
Paragraph
;
CanvasParagraph
paragraph
=
builder
.
build
()
as
Canvas
Paragraph
;
expect
(
paragraph
.
plainText
,
isNotNull
);
expect
(
paragraph
.
geometric
Style
.
fontWeight
,
FontWeight
.
normal
);
expect
(
paragraph
.
paragraph
Style
.
fontWeight
,
FontWeight
.
normal
);
builder
=
Dom
ParagraphBuilder
(
EngineParagraphStyle
(
builder
=
ParagraphBuilder
(
EngineParagraphStyle
(
fontFamily:
'sans-serif'
,
fontStyle:
FontStyle
.
normal
,
fontWeight:
FontWeight
.
normal
,
...
...
@@ -173,13 +170,12 @@ Future<void> testMain() async {
));
builder
.
pushStyle
(
TextStyle
(
fontWeight:
FontWeight
.
bold
));
builder
.
addText
(
'hi'
);
paragraph
=
builder
.
build
()
as
Dom
Paragraph
;
paragraph
=
builder
.
build
()
as
Canvas
Paragraph
;
expect
(
paragraph
.
plainText
,
isNotNull
);
expect
(
paragraph
.
geometricStyle
.
fontWeight
,
FontWeight
.
bold
);
});
test
(
'
$ParagraphBuilder
detects rich text'
,
()
{
final
DomParagraphBuilder
builder
=
Dom
ParagraphBuilder
(
EngineParagraphStyle
(
final
ParagraphBuilder
builder
=
ParagraphBuilder
(
EngineParagraphStyle
(
fontFamily:
'sans-serif'
,
fontStyle:
FontStyle
.
normal
,
fontWeight:
FontWeight
.
normal
,
...
...
@@ -188,176 +184,27 @@ Future<void> testMain() async {
builder
.
addText
(
'h'
);
builder
.
pushStyle
(
TextStyle
(
fontWeight:
FontWeight
.
bold
));
builder
.
addText
(
'i'
);
final
DomParagraph
paragraph
=
builder
.
build
()
as
DomParagraph
;
expect
(
paragraph
.
plainText
,
isNull
);
expect
(
paragraph
.
geometricStyle
.
fontWeight
,
FontWeight
.
normal
);
final
CanvasParagraph
paragraph
=
builder
.
build
()
as
CanvasParagraph
;
expect
(
paragraph
.
plainText
,
'hi'
);
});
test
(
'
$ParagraphBuilder
treats empty text as plain'
,
()
{
final
DomParagraphBuilder
builder
=
Dom
ParagraphBuilder
(
EngineParagraphStyle
(
final
ParagraphBuilder
builder
=
ParagraphBuilder
(
EngineParagraphStyle
(
fontFamily:
'sans-serif'
,
fontStyle:
FontStyle
.
normal
,
fontWeight:
FontWeight
.
normal
,
fontSize:
15.0
,
));
builder
.
pushStyle
(
TextStyle
(
fontWeight:
FontWeight
.
bold
));
final
DomParagraph
paragraph
=
builder
.
build
()
as
Dom
Paragraph
;
final
CanvasParagraph
paragraph
=
builder
.
build
()
as
Canvas
Paragraph
;
expect
(
paragraph
.
plainText
,
''
);
expect
(
paragraph
.
geometricStyle
.
fontWeight
,
FontWeight
.
bold
);
});
// Regression test for https://github.com/flutter/flutter/issues/34931.
test
(
'hit test on styled text returns correct span offset'
,
()
{
final
DomParagraphBuilder
builder
=
DomParagraphBuilder
(
EngineParagraphStyle
(
fontFamily:
'sans-serif'
,
fontStyle:
FontStyle
.
normal
,
fontWeight:
FontWeight
.
normal
,
fontSize:
15.0
,
));
builder
.
pushStyle
(
TextStyle
(
fontWeight:
FontWeight
.
bold
));
const
String
firstSpanText
=
'XYZ'
;
builder
.
addText
(
firstSpanText
);
builder
.
pushStyle
(
TextStyle
(
fontWeight:
FontWeight
.
normal
));
const
String
secondSpanText
=
'1234'
;
builder
.
addText
(
secondSpanText
);
builder
.
pushStyle
(
TextStyle
(
fontStyle:
FontStyle
.
italic
));
builder
.
addText
(
'followed by a link'
);
final
DomParagraph
paragraph
=
builder
.
build
()
as
DomParagraph
;
paragraph
.
layout
(
const
ParagraphConstraints
(
width:
800.0
));
expect
(
paragraph
.
plainText
,
isNull
);
const
int
secondSpanStartPosition
=
firstSpanText
.
length
;
const
int
thirdSpanStartPosition
=
firstSpanText
.
length
+
secondSpanText
.
length
;
expect
(
paragraph
.
getPositionForOffset
(
const
Offset
(
50
,
0
)).
offset
,
secondSpanStartPosition
);
expect
(
paragraph
.
getPositionForOffset
(
const
Offset
(
150
,
0
)).
offset
,
thirdSpanStartPosition
);
});
test
(
'hit test on the nested text span and returns correct span offset'
,
()
{
const
String
fontFamily
=
'sans-serif'
;
const
double
fontSize
=
20.0
;
final
TextStyle
style
=
TextStyle
(
fontFamily:
fontFamily
,
fontSize:
fontSize
);
final
DomParagraphBuilder
builder
=
DomParagraphBuilder
(
EngineParagraphStyle
(
fontFamily:
fontFamily
,
fontSize:
fontSize
,
));
const
String
text00
=
'test test test test test te00 '
;
const
String
text010
=
'test010 '
;
const
String
text02
=
'test test test test te02 '
;
const
String
text030
=
'test030 '
;
const
String
text04
=
'test test test test test test test test test test te04 '
;
const
String
text050
=
'test050 '
;
/* Logical arrangement: Tree
Root TextSpan: 0
*/
builder
.
pushStyle
(
style
);
{
// 1st child TextSpan of Root: 0.0
builder
.
pushStyle
(
style
);
builder
.
addText
(
text00
);
builder
.
pop
();
// 2nd child TextSpan of Root: 0.1
builder
.
pushStyle
(
style
);
{
// 1st child TextSpan of 0.1: 0.1.0
builder
.
pushStyle
(
style
);
builder
.
addText
(
text010
);
builder
.
pop
();
}
builder
.
pop
();
// 3rd child TextSpan of Root: 0.2
builder
.
pushStyle
(
style
);
builder
.
addText
(
text02
);
builder
.
pop
();
// 4th child TextSpan of Root: 0.3
builder
.
pushStyle
(
style
);
{
// 1st child TextSpan of 0.3: 0.3.0
builder
.
pushStyle
(
style
);
builder
.
addText
(
text030
);
builder
.
pop
();
}
builder
.
pop
();
// 5th child TextSpan of Root: 0.4
builder
.
pushStyle
(
style
);
builder
.
addText
(
text04
);
builder
.
pop
();
// 6th child TextSpan of Root: 0.5
builder
.
pushStyle
(
style
);
{
// 1st child TextSpan of 0.5: 0.5.0
builder
.
pushStyle
(
style
);
builder
.
addText
(
text050
);
builder
.
pop
();
}
builder
.
pop
();
}
builder
.
pop
();
/* Display arrangement: Visible texts
Because `const fontSize = 20.0`, the width of each character is 20 and the
height is 20. `Display arrangement` squashes `Logical arrangement` to the
(x, y) plane. That means `Display arrangement` only shows the visible texts.
The order of texts is text00 --> text010 --> text02 --> text030 --> text04
--> text050.
The output is like that.
|------------ 600 ------------| Begin of test010
|--------------- 760 ----------------| End of test010
|---------- 500 ---------| Begin of test030
|------------- 660 -------------| End of test030
|-- 180 --| Begin of test050
|------ 360 -----| End of test050
'test test test test test te00 test010 '
'test test test test te02 test030 test '
'test test test test test test test test '
'test te04 test050 '
*/
final
DomParagraph
paragraph
=
builder
.
build
()
as
DomParagraph
;
paragraph
.
layout
(
const
ParagraphConstraints
(
width:
800
));
// Reference the offsets with the output of `Display arrangement`.
const
int
offset010
=
text00
.
length
;
const
int
offset030
=
offset010
+
text010
.
length
+
text02
.
length
;
const
int
offset04
=
offset030
+
text030
.
length
;
const
int
offset050
=
offset04
+
text04
.
length
;
// Tap text010.
expect
(
paragraph
.
getPositionForOffset
(
const
Offset
(
700
,
10
)).
offset
,
offset010
);
// Tap text030
expect
(
paragraph
.
getPositionForOffset
(
const
Offset
(
600
,
30
)).
offset
,
offset030
);
// Tap text050
expect
(
paragraph
.
getPositionForOffset
(
const
Offset
(
220
,
70
)).
offset
,
offset050
);
// Tap the left neighbor of text050
expect
(
paragraph
.
getPositionForOffset
(
const
Offset
(
199
,
70
)).
offset
,
offset04
);
// Tap the right neighbor of text050. No matter who the right neighbor of
// text0505 is, it must not be text050 itself.
expect
(
paragraph
.
getPositionForOffset
(
const
Offset
(
360
,
70
)).
offset
,
isNot
(
offset050
));
// Tap the neighbor above text050
expect
(
paragraph
.
getPositionForOffset
(
const
Offset
(
220
,
59
)).
offset
,
offset04
);
// Tap the neighbor below text050. No matter who the neighbor above text050,
// it must not be text050 itself.
expect
(
paragraph
.
getPositionForOffset
(
const
Offset
(
220
,
80
)).
offset
,
isNot
(
offset050
));
});
// Regression test for https://github.com/flutter/flutter/issues/38972
test
(
'should not set fontFamily to effectiveFontFamily for spans in rich text'
,
()
{
final
DomParagraphBuilder
builder
=
Dom
ParagraphBuilder
(
EngineParagraphStyle
(
final
ParagraphBuilder
builder
=
ParagraphBuilder
(
EngineParagraphStyle
(
fontFamily:
'Roboto'
,
fontStyle:
FontStyle
.
normal
,
fontWeight:
FontWeight
.
normal
,
...
...
@@ -370,11 +217,11 @@ Future<void> testMain() async {
builder
.
pushStyle
(
TextStyle
(
fontSize:
30.0
,
fontWeight:
FontWeight
.
normal
));
const
String
secondSpanText
=
'def'
;
builder
.
addText
(
secondSpanText
);
final
DomParagraph
paragraph
=
builder
.
build
()
as
Dom
Paragraph
;
final
CanvasParagraph
paragraph
=
builder
.
build
()
as
Canvas
Paragraph
;
paragraph
.
layout
(
const
ParagraphConstraints
(
width:
800.0
));
expect
(
paragraph
.
plainText
,
isNull
);
expect
(
paragraph
.
plainText
,
'abcdef'
);
final
List
<
SpanElement
>
spans
=
paragraph
.
paragraphElement
.
querySelectorAll
(
'span'
);
paragraph
.
toDomElement
()
.
querySelectorAll
(
'span'
);
expect
(
spans
[
0
].
style
.
fontFamily
,
'Ahem,
$fallback
, sans-serif'
);
// The nested span here should not set it's family to default sans-serif.
expect
(
spans
[
1
].
style
.
fontFamily
,
'Ahem,
$fallback
, sans-serif'
);
...
...
@@ -388,15 +235,13 @@ Future<void> testMain() async {
// Set this to false so it doesn't default to 'Ahem' font.
debugEmulateFlutterTesterEnvironment
=
false
;
final
DomParagraphBuilder
builder
=
DomParagraphBuilder
(
EngineParagraphStyle
(
final
CanvasParagraph
paragraph
=
plain
(
EngineParagraphStyle
(
fontFamily:
'SomeFont'
,
fontSize:
12.0
,
));
builder
.
addText
(
'Hello'
);
),
'Hello'
);
final
DomParagraph
paragraph
=
builder
.
build
()
as
DomParagraph
;
expect
(
paragraph
.
paragraphElement
.
style
.
fontFamily
,
paragraph
.
layout
(
constrain
(
double
.
infinity
))
;
expect
(
paragraph
.
toDomElement
()
.
style
.
fontFamily
,
'SomeFont,
$fallback
, sans-serif'
);
debugEmulateFlutterTesterEnvironment
=
true
;
...
...
@@ -410,15 +255,13 @@ Future<void> testMain() async {
// Set this to false so it doesn't default to 'Ahem' font.
debugEmulateFlutterTesterEnvironment
=
false
;
final
DomParagraphBuilder
builder
=
DomParagraphBuilder
(
EngineParagraphStyle
(
final
CanvasParagraph
paragraph
=
plain
(
EngineParagraphStyle
(
fontFamily:
'serif'
,
fontSize:
12.0
,
));
)
,
'Hello'
);
builder
.
addText
(
'Hello'
);
final
DomParagraph
paragraph
=
builder
.
build
()
as
DomParagraph
;
expect
(
paragraph
.
paragraphElement
.
style
.
fontFamily
,
'serif'
);
paragraph
.
layout
(
constrain
(
double
.
infinity
));
expect
(
paragraph
.
toDomElement
().
style
.
fontFamily
,
'serif'
);
debugEmulateFlutterTesterEnvironment
=
true
;
});
...
...
@@ -427,15 +270,13 @@ Future<void> testMain() async {
// Set this to false so it doesn't default to 'Ahem' font.
debugEmulateFlutterTesterEnvironment
=
false
;
final
DomParagraphBuilder
builder
=
DomParagraphBuilder
(
EngineParagraphStyle
(
final
CanvasParagraph
paragraph
=
plain
(
EngineParagraphStyle
(
fontFamily:
'MyFont 2000'
,
fontSize:
12.0
,
));
builder
.
addText
(
'Hello'
);
),
'Hello'
);
final
DomParagraph
paragraph
=
builder
.
build
()
as
DomParagraph
;
expect
(
paragraph
.
paragraphElement
.
style
.
fontFamily
,
paragraph
.
layout
(
constrain
(
double
.
infinity
))
;
expect
(
paragraph
.
toDomElement
()
.
style
.
fontFamily
,
'"MyFont 2000",
$fallback
, sans-serif'
);
debugEmulateFlutterTesterEnvironment
=
true
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录