Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
sxychenjing
engine
提交
d941aefa
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,发现更多精彩内容 >>
未验证
提交
d941aefa
编写于
12月 17, 2020
作者:
M
Mouad Debbar
提交者:
GitHub
12月 17, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[web] Rich text painting on bitmap canvas (#23136)
上级
a8c360dc
变更
10
隐藏空白更改
内联
并排
Showing
10 changed file
with
437 addition
and
11 deletion
+437
-11
ci/licenses_golden/licenses_flutter
ci/licenses_golden/licenses_flutter
+1
-0
lib/web_ui/dev/goldens_lock.yaml
lib/web_ui/dev/goldens_lock.yaml
+1
-1
lib/web_ui/lib/src/engine.dart
lib/web_ui/lib/src/engine.dart
+1
-0
lib/web_ui/lib/src/engine/text/canvas_paragraph.dart
lib/web_ui/lib/src/engine/text/canvas_paragraph.dart
+7
-8
lib/web_ui/lib/src/engine/text/layout_service.dart
lib/web_ui/lib/src/engine/text/layout_service.dart
+14
-0
lib/web_ui/lib/src/engine/text/paint_service.dart
lib/web_ui/lib/src/engine/text/paint_service.dart
+80
-0
lib/web_ui/test/golden_tests/engine/canvas_paragraph/general_test.dart
...st/golden_tests/engine/canvas_paragraph/general_test.dart
+168
-0
lib/web_ui/test/golden_tests/engine/canvas_paragraph/helper.dart
..._ui/test/golden_tests/engine/canvas_paragraph/helper.dart
+34
-0
lib/web_ui/test/golden_tests/engine/canvas_paragraph/overflow_test.dart
...t/golden_tests/engine/canvas_paragraph/overflow_test.dart
+130
-0
lib/web_ui/test/text/layout_service_helper.dart
lib/web_ui/test/text/layout_service_helper.dart
+1
-2
未找到文件。
ci/licenses_golden/licenses_flutter
浏览文件 @
d941aefa
...
...
@@ -1184,6 +1184,7 @@ FILE: ../../../flutter/lib/web_ui/lib/src/engine/text/layout_service.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/text/line_break_properties.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/text/line_breaker.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/text/measurement.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/text/paint_service.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/text/paragraph.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/text/ruler.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/text/unicode_range.dart
...
...
lib/web_ui/dev/goldens_lock.yaml
浏览文件 @
d941aefa
repository
:
https://github.com/flutter/goldens.git
revision
:
c808c28c81b6c3143ae969e8c49bed4a6d49aabb
revision
:
4946ab2de031c14d30502efcaf51220e0be4d1f1
lib/web_ui/lib/src/engine.dart
浏览文件 @
d941aefa
...
...
@@ -129,6 +129,7 @@ part 'engine/text/layout_service.dart';
part
'engine/text/line_break_properties.dart'
;
part
'engine/text/line_breaker.dart'
;
part
'engine/text/measurement.dart'
;
part
'engine/text/paint_service.dart'
;
part
'engine/text/paragraph.dart'
;
part
'engine/text/canvas_paragraph.dart'
;
part
'engine/text/ruler.dart'
;
...
...
lib/web_ui/lib/src/engine/text/canvas_paragraph.dart
浏览文件 @
d941aefa
...
...
@@ -58,9 +58,13 @@ class CanvasParagraph implements EngineParagraph {
@override
bool
get
didExceedMaxLines
=>
_layoutService
.
didExceedMaxLines
;
@override
bool
isLaidOut
=
false
;
ui
.
ParagraphConstraints
?
_lastUsedConstraints
;
late
final
TextLayoutService
_layoutService
=
TextLayoutService
(
this
);
late
final
TextPaintService
_paintService
=
TextPaintService
(
this
);
@override
void
layout
(
ui
.
ParagraphConstraints
constraints
)
{
...
...
@@ -90,6 +94,7 @@ class CanvasParagraph implements EngineParagraph {
.
benchmark
(
'text_layout'
,
stopwatch
.
elapsedMicroseconds
.
toDouble
());
}
isLaidOut
=
true
;
_lastUsedConstraints
=
constraints
;
}
...
...
@@ -100,10 +105,7 @@ class CanvasParagraph implements EngineParagraph {
@override
void
paint
(
BitmapCanvas
canvas
,
ui
.
Offset
offset
)
{
// TODO(mdebbar): Loop through the spans and for each box in the span:
// 1. Paint the background rect.
// 2. Paint the text shadows?
// 3. Paint the text.
_paintService
.
paint
(
canvas
,
offset
);
}
@override
...
...
@@ -182,9 +184,6 @@ class CanvasParagraph implements EngineParagraph {
@override
final
bool
drawOnCanvas
=
true
;
@override
bool
isLaidOut
=
false
;
@override
List
<
ui
.
TextBox
>
getBoxesForRange
(
int
start
,
...
...
@@ -217,7 +216,7 @@ class CanvasParagraph implements EngineParagraph {
}
@override
List
<
ui
.
LineMetrics
>
computeLineMetrics
()
{
List
<
Engine
LineMetrics
>
computeLineMetrics
()
{
return
_layoutService
.
lines
;
}
}
...
...
lib/web_ui/lib/src/engine/text/layout_service.dart
浏览文件 @
d941aefa
...
...
@@ -370,6 +370,14 @@ class RangeBox {
return
startIndex
<
this
.
end
.
index
&&
this
.
start
.
index
<
endIndex
;
}
/// Returns a [ui.TextBox] representing this range box in the given [line].
///
/// The coordinates of the resulting [ui.TextBox] are relative to the
/// paragraph, not to the line.
ui
.
TextBox
toTextBox
(
EngineLineMetrics
line
)
{
return
intersect
(
line
,
start
.
index
,
end
.
index
);
}
/// Performs the intersection of this box with the range given by [start] and
/// [end] indices, and returns a [ui.TextBox] representing that intersection.
///
...
...
@@ -772,6 +780,12 @@ class LineBuilder {
);
extendTo
(
LineBreakResult
.
sameIndex
(
breakingPoint
,
LineBreakType
.
prohibited
));
// There's a possibility that the end of line has moved backwards, so we
// need to remove some boxes in that case.
while
(
_boxes
.
length
>
0
&&
_boxes
.
last
.
end
.
index
>
breakingPoint
)
{
_boxes
.
removeLast
();
}
}
LineBreakResult
get
_boxStart
{
...
...
lib/web_ui/lib/src/engine/text/paint_service.dart
0 → 100644
浏览文件 @
d941aefa
// 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
part of
engine
;
/// Responsible for painting a [CanvasParagraph] on a [BitmapCanvas].
class
TextPaintService
{
TextPaintService
(
this
.
paragraph
);
final
CanvasParagraph
paragraph
;
void
paint
(
BitmapCanvas
canvas
,
ui
.
Offset
offset
)
{
// Loop through all the lines, for each line, loop through all the boxes and
// paint them. The boxes have enough information so they can be painted
// individually.
final
List
<
EngineLineMetrics
>
lines
=
paragraph
.
computeLineMetrics
();
for
(
final
EngineLineMetrics
line
in
lines
)
{
for
(
final
RangeBox
box
in
line
.
boxes
!)
{
_paintBox
(
canvas
,
offset
,
line
,
box
);
}
}
}
void
_paintBox
(
BitmapCanvas
canvas
,
ui
.
Offset
offset
,
EngineLineMetrics
line
,
RangeBox
box
,
)
{
final
ParagraphSpan
span
=
box
.
span
;
// Placeholder spans don't need any painting. Their boxes should remain
// empty so that their underlying widgets do their own painting.
if
(
span
is
FlatTextSpan
)
{
// Paint the background of the box, if the span has a background.
final
SurfacePaint
?
background
=
span
.
style
.
_background
as
SurfacePaint
?;
if
(
background
!=
null
)
{
canvas
.
drawRect
(
box
.
toTextBox
(
line
).
toRect
().
shift
(
offset
),
background
.
paintData
,
);
}
// Paint the actual text.
_applySpanStyleToCanvas
(
span
,
canvas
);
final
double
x
=
offset
.
dx
+
line
.
left
+
box
.
left
;
final
double
y
=
offset
.
dy
+
line
.
baseline
;
final
String
text
=
paragraph
.
toPlainText
().
substring
(
box
.
start
.
index
,
box
.
end
.
indexWithoutTrailingNewlines
,
);
canvas
.
fillText
(
text
,
x
,
y
);
// Paint the ellipsis using the same span styles.
final
String
?
ellipsis
=
line
.
ellipsis
;
if
(
ellipsis
!=
null
&&
box
==
line
.
boxes
!.
last
)
{
final
double
x
=
offset
.
dx
+
line
.
left
+
box
.
right
;
canvas
.
fillText
(
ellipsis
,
x
,
y
);
}
canvas
.
_tearDownPaint
();
}
}
void
_applySpanStyleToCanvas
(
FlatTextSpan
span
,
BitmapCanvas
canvas
)
{
final
SurfacePaint
?
paint
;
final
ui
.
Paint
?
foreground
=
span
.
style
.
_foreground
;
if
(
foreground
!=
null
)
{
paint
=
foreground
as
SurfacePaint
;
}
else
{
paint
=
(
ui
.
Paint
()..
color
=
span
.
style
.
_color
!)
as
SurfacePaint
;
}
canvas
.
setCssFont
(
span
.
style
.
cssFontString
);
canvas
.
_setUpPaint
(
paint
.
paintData
,
null
);
}
}
lib/web_ui/test/golden_tests/engine/canvas_paragraph/general_test.dart
0 → 100644
浏览文件 @
d941aefa
// 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.6
import
'dart:async'
;
import
'package:test/bootstrap/browser.dart'
;
import
'package:test/test.dart'
;
import
'package:ui/ui.dart'
hide
window
;
import
'package:ui/src/engine.dart'
;
import
'../scuba.dart'
;
import
'helper.dart'
;
typedef
CanvasTest
=
FutureOr
<
void
>
Function
(
EngineCanvas
canvas
);
const
Rect
bounds
=
Rect
.
fromLTWH
(
0
,
0
,
800
,
600
);
const
Color
white
=
Color
(
0xFFFFFFFF
);
const
Color
black
=
Color
(
0xFF000000
);
const
Color
red
=
Color
(
0xFFFF0000
);
const
Color
green
=
Color
(
0xFF00FF00
);
const
Color
blue
=
Color
(
0xFF0000FF
);
ParagraphConstraints
constrain
(
double
width
)
{
return
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
);
}
void
testMain
(
)
async
{
setUpStableTestFonts
();
test
(
'paints spans and lines correctly'
,
()
{
final
canvas
=
BitmapCanvas
(
bounds
,
RenderStrategy
());
Offset
offset
=
Offset
.
zero
;
CanvasParagraph
paragraph
;
// Single-line multi-span.
paragraph
=
rich
(
ParagraphStyle
(
fontFamily:
'Roboto'
),
(
builder
)
{
builder
.
pushStyle
(
EngineTextStyle
.
only
(
color:
blue
));
builder
.
addText
(
'Lorem '
);
builder
.
pushStyle
(
EngineTextStyle
.
only
(
color:
green
,
background:
Paint
()..
color
=
red
,
));
builder
.
addText
(
'ipsum '
);
builder
.
pop
();
builder
.
addText
(
'.'
);
})
..
layout
(
constrain
(
double
.
infinity
));
canvas
.
drawParagraph
(
paragraph
,
offset
);
offset
=
offset
.
translate
(
0
,
paragraph
.
height
+
10
);
// Multi-line single-span.
paragraph
=
rich
(
ParagraphStyle
(
fontFamily:
'Roboto'
),
(
builder
)
{
builder
.
addText
(
'Lorem ipsum dolor sit'
);
})
..
layout
(
constrain
(
90.0
));
canvas
.
drawParagraph
(
paragraph
,
offset
);
offset
=
offset
.
translate
(
0
,
paragraph
.
height
+
10
);
// Multi-line multi-span.
paragraph
=
rich
(
ParagraphStyle
(
fontFamily:
'Roboto'
),
(
builder
)
{
builder
.
pushStyle
(
EngineTextStyle
.
only
(
color:
blue
));
builder
.
addText
(
'Lorem ipsum '
);
builder
.
pushStyle
(
EngineTextStyle
.
only
(
background:
Paint
()..
color
=
red
));
builder
.
pushStyle
(
EngineTextStyle
.
only
(
color:
green
));
builder
.
addText
(
'dolor '
);
builder
.
pop
();
builder
.
addText
(
'sit'
);
})
..
layout
(
constrain
(
90.0
));
canvas
.
drawParagraph
(
paragraph
,
offset
);
offset
=
offset
.
translate
(
0
,
paragraph
.
height
+
10
);
return
takeScreenshot
(
canvas
,
bounds
,
'canvas_paragraph_general'
);
});
test
(
'respects alignment'
,
()
{
final
canvas
=
BitmapCanvas
(
bounds
,
RenderStrategy
());
Offset
offset
=
Offset
.
zero
;
CanvasParagraph
paragraph
;
void
build
(
CanvasParagraphBuilder
builder
)
{
builder
.
pushStyle
(
EngineTextStyle
.
only
(
color:
black
));
builder
.
addText
(
'Lorem '
);
builder
.
pushStyle
(
EngineTextStyle
.
only
(
color:
blue
));
builder
.
addText
(
'ipsum '
);
builder
.
pushStyle
(
EngineTextStyle
.
only
(
color:
green
));
builder
.
addText
(
'dolor '
);
builder
.
pushStyle
(
EngineTextStyle
.
only
(
color:
red
));
builder
.
addText
(
'sit'
);
}
paragraph
=
rich
(
ParagraphStyle
(
fontFamily:
'Roboto'
,
textAlign:
TextAlign
.
left
),
build
,
)..
layout
(
constrain
(
100.0
));
canvas
.
drawParagraph
(
paragraph
,
offset
);
offset
=
offset
.
translate
(
0
,
paragraph
.
height
+
10
);
paragraph
=
rich
(
ParagraphStyle
(
fontFamily:
'Roboto'
,
textAlign:
TextAlign
.
center
),
build
,
)..
layout
(
constrain
(
100.0
));
canvas
.
drawParagraph
(
paragraph
,
offset
);
offset
=
offset
.
translate
(
0
,
paragraph
.
height
+
10
);
paragraph
=
rich
(
ParagraphStyle
(
fontFamily:
'Roboto'
,
textAlign:
TextAlign
.
right
),
build
,
)..
layout
(
constrain
(
100.0
));
canvas
.
drawParagraph
(
paragraph
,
offset
);
offset
=
offset
.
translate
(
0
,
paragraph
.
height
+
10
);
return
takeScreenshot
(
canvas
,
bounds
,
'canvas_paragraph_align'
);
});
test
(
'paints spans with varying heights/baselines'
,
()
{
final
canvas
=
BitmapCanvas
(
bounds
,
RenderStrategy
());
final
CanvasParagraph
paragraph
=
rich
(
ParagraphStyle
(
fontFamily:
'Roboto'
),
(
builder
)
{
builder
.
pushStyle
(
EngineTextStyle
.
only
(
fontSize:
20.0
));
builder
.
addText
(
'Lorem '
);
builder
.
pushStyle
(
EngineTextStyle
.
only
(
fontSize:
40.0
,
background:
Paint
()..
color
=
green
,
));
builder
.
addText
(
'ipsum '
);
builder
.
pushStyle
(
EngineTextStyle
.
only
(
fontSize:
10.0
,
color:
white
,
background:
Paint
()..
color
=
black
,
));
builder
.
addText
(
'dolor '
);
builder
.
pushStyle
(
EngineTextStyle
.
only
(
fontSize:
30.0
));
builder
.
addText
(
'sit '
);
builder
.
pop
();
builder
.
pop
();
builder
.
pushStyle
(
EngineTextStyle
.
only
(
fontSize:
20.0
,
background:
Paint
()..
color
=
blue
,
));
builder
.
addText
(
'amet'
);
},
)..
layout
(
constrain
(
220.0
));
canvas
.
drawParagraph
(
paragraph
,
Offset
.
zero
);
return
takeScreenshot
(
canvas
,
bounds
,
'canvas_paragraph_varying_heights'
);
});
}
lib/web_ui/test/golden_tests/engine/canvas_paragraph/helper.dart
0 → 100644
浏览文件 @
d941aefa
// 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
'dart:html'
as
html
;
import
'package:ui/src/engine.dart'
;
import
'package:ui/ui.dart'
;
import
'package:web_engine_tester/golden_tester.dart'
;
Future
<
void
>
takeScreenshot
(
EngineCanvas
canvas
,
Rect
region
,
String
fileName
,
{
bool
write
=
false
,
double
?
maxDiffRatePercent
,
})
async
{
final
html
.
Element
sceneElement
=
html
.
Element
.
tag
(
'flt-scene'
);
try
{
sceneElement
.
append
(
canvas
.
rootElement
);
html
.
document
.
body
!.
append
(
sceneElement
);
await
matchGoldenFile
(
'
$fileName
.png'
,
region:
region
,
maxDiffRatePercent:
maxDiffRatePercent
,
write:
write
,
);
}
finally
{
// The page is reused across tests, so remove the element after taking the
// Scuba screenshot.
sceneElement
.
remove
();
}
}
lib/web_ui/test/golden_tests/engine/canvas_paragraph/overflow_test.dart
0 → 100644
浏览文件 @
d941aefa
// 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.6
import
'dart:async'
;
import
'package:test/bootstrap/browser.dart'
;
import
'package:test/test.dart'
;
import
'package:ui/ui.dart'
hide
window
;
import
'package:ui/src/engine.dart'
;
import
'../scuba.dart'
;
import
'helper.dart'
;
typedef
CanvasTest
=
FutureOr
<
void
>
Function
(
EngineCanvas
canvas
);
const
Rect
bounds
=
Rect
.
fromLTWH
(
0
,
0
,
800
,
600
);
const
Color
white
=
Color
(
0xFFFFFFFF
);
const
Color
black
=
Color
(
0xFF000000
);
const
Color
red
=
Color
(
0xFFFF0000
);
const
Color
green
=
Color
(
0xFF00FF00
);
const
Color
blue
=
Color
(
0xFF0000FF
);
ParagraphConstraints
constrain
(
double
width
)
{
return
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
);
}
void
testMain
(
)
async
{
setUpStableTestFonts
();
test
(
'ellipsis'
,
()
{
final
canvas
=
BitmapCanvas
(
bounds
,
RenderStrategy
());
Offset
offset
=
Offset
.
zero
;
CanvasParagraph
paragraph
;
paragraph
=
rich
(
ParagraphStyle
(
fontFamily:
'Roboto'
,
ellipsis:
'...'
),
(
builder
)
{
builder
.
pushStyle
(
EngineTextStyle
.
only
(
color:
blue
));
builder
.
addText
(
'Lorem '
);
builder
.
pushStyle
(
EngineTextStyle
.
only
(
color:
green
));
builder
.
addText
(
'ipsum'
);
},
)..
layout
(
constrain
(
80.0
));
canvas
.
drawParagraph
(
paragraph
,
offset
);
offset
=
offset
.
translate
(
0
,
paragraph
.
height
+
10
);
paragraph
=
rich
(
ParagraphStyle
(
fontFamily:
'Roboto'
,
ellipsis:
'...'
),
(
builder
)
{
builder
.
pushStyle
(
EngineTextStyle
.
only
(
color:
blue
));
builder
.
addText
(
'Lorem
\n
'
);
builder
.
pushStyle
(
EngineTextStyle
.
only
(
color:
green
));
builder
.
addText
(
'ipsum '
);
builder
.
pushStyle
(
EngineTextStyle
.
only
(
color:
red
));
builder
.
addText
(
'dolor sit'
);
},
)..
layout
(
constrain
(
80.0
));
canvas
.
drawParagraph
(
paragraph
,
offset
);
offset
=
offset
.
translate
(
0
,
paragraph
.
height
+
10
);
paragraph
=
rich
(
ParagraphStyle
(
fontFamily:
'Roboto'
,
ellipsis:
'...'
),
(
builder
)
{
builder
.
pushStyle
(
EngineTextStyle
.
only
(
color:
blue
));
builder
.
addText
(
'Lorem
\n
'
);
builder
.
pushStyle
(
EngineTextStyle
.
only
(
color:
green
));
builder
.
addText
(
'ipsum '
);
builder
.
pushStyle
(
EngineTextStyle
.
only
(
color:
red
));
builder
.
addText
(
'd'
);
builder
.
pushStyle
(
EngineTextStyle
.
only
(
color:
black
));
builder
.
addText
(
'o'
);
builder
.
pushStyle
(
EngineTextStyle
.
only
(
color:
blue
));
builder
.
addText
(
'l'
);
builder
.
pushStyle
(
EngineTextStyle
.
only
(
color:
green
));
builder
.
addText
(
'o'
);
builder
.
pushStyle
(
EngineTextStyle
.
only
(
color:
red
));
builder
.
addText
(
'r'
);
builder
.
pushStyle
(
EngineTextStyle
.
only
(
color:
black
));
builder
.
addText
(
' '
);
builder
.
pushStyle
(
EngineTextStyle
.
only
(
color:
blue
));
builder
.
addText
(
's'
);
builder
.
pushStyle
(
EngineTextStyle
.
only
(
color:
green
));
builder
.
addText
(
'i'
);
builder
.
pushStyle
(
EngineTextStyle
.
only
(
color:
red
));
builder
.
addText
(
't'
);
},
)..
layout
(
constrain
(
80.0
));
canvas
.
drawParagraph
(
paragraph
,
offset
);
offset
=
offset
.
translate
(
0
,
paragraph
.
height
+
10
);
paragraph
=
rich
(
ParagraphStyle
(
fontFamily:
'Roboto'
,
maxLines:
2
,
ellipsis:
'...'
),
(
builder
)
{
builder
.
pushStyle
(
EngineTextStyle
.
only
(
color:
blue
));
builder
.
addText
(
'Lorem'
);
builder
.
pushStyle
(
EngineTextStyle
.
only
(
color:
green
));
builder
.
addText
(
'ipsum'
);
builder
.
pushStyle
(
EngineTextStyle
.
only
(
color:
red
));
builder
.
addText
(
'dolor'
);
builder
.
pushStyle
(
EngineTextStyle
.
only
(
color:
black
));
builder
.
addText
(
'sit'
);
builder
.
pushStyle
(
EngineTextStyle
.
only
(
color:
blue
));
builder
.
addText
(
'amet'
);
builder
.
pushStyle
(
EngineTextStyle
.
only
(
color:
blue
));
builder
.
addText
(
'consectetur'
);
},
)..
layout
(
constrain
(
80.0
));
canvas
.
drawParagraph
(
paragraph
,
offset
);
offset
=
offset
.
translate
(
0
,
paragraph
.
height
+
10
);
return
takeScreenshot
(
canvas
,
bounds
,
'canvas_paragraph_ellipsis'
);
});
}
lib/web_ui/test/text/layout_service_helper.dart
浏览文件 @
d941aefa
...
...
@@ -35,8 +35,7 @@ TestLine l(
void
expectLines
(
CanvasParagraph
paragraph
,
List
<
TestLine
>
expectedLines
)
{
final
String
text
=
paragraph
.
toPlainText
();
final
List
<
EngineLineMetrics
>
lines
=
paragraph
.
computeLineMetrics
()
as
List
<
EngineLineMetrics
>;
final
List
<
EngineLineMetrics
>
lines
=
paragraph
.
computeLineMetrics
();
expect
(
lines
,
hasLength
(
expectedLines
.
length
));
for
(
int
i
=
0
;
i
<
lines
.
length
;
i
++)
{
final
EngineLineMetrics
line
=
lines
[
i
];
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录