Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
sxychenjing
engine
提交
a4abfb23
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,发现更多精彩内容 >>
未验证
提交
a4abfb23
编写于
6月 03, 2019
作者:
G
Gary Qian
提交者:
GitHub
6月 03, 2019
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Text inline widget LibTxt/dart:ui implementation (#8207)
上级
f9ce0167
变更
22
展开全部
隐藏空白更改
内联
并排
Showing
22 changed file
with
1939 addition
and
111 deletion
+1939
-111
ci/licenses_golden/licenses_flutter
ci/licenses_golden/licenses_flutter
+2
-0
lib/stub_ui/lib/src/ui/text.dart
lib/stub_ui/lib/src/ui/text.dart
+127
-6
lib/ui/text.dart
lib/ui/text.dart
+190
-62
lib/ui/text/paragraph.cc
lib/ui/text/paragraph.cc
+18
-13
lib/ui/text/paragraph.h
lib/ui/text/paragraph.h
+1
-0
lib/ui/text/paragraph_builder.cc
lib/ui/text/paragraph_builder.cc
+20
-4
lib/ui/text/paragraph_builder.h
lib/ui/text/paragraph_builder.h
+13
-0
lib/ui/text/paragraph_impl.h
lib/ui/text/paragraph_impl.h
+2
-0
lib/ui/text/paragraph_impl_txt.cc
lib/ui/text/paragraph_impl_txt.cc
+11
-0
lib/ui/text/paragraph_impl_txt.h
lib/ui/text/paragraph_impl_txt.h
+1
-0
third_party/txt/BUILD.gn
third_party/txt/BUILD.gn
+2
-0
third_party/txt/src/minikin/LineBreaker.cpp
third_party/txt/src/minikin/LineBreaker.cpp
+8
-0
third_party/txt/src/minikin/LineBreaker.h
third_party/txt/src/minikin/LineBreaker.h
+7
-0
third_party/txt/src/txt/paint_record.cc
third_party/txt/src/txt/paint_record.cc
+22
-0
third_party/txt/src/txt/paint_record.h
third_party/txt/src/txt/paint_record.h
+19
-0
third_party/txt/src/txt/paragraph.cc
third_party/txt/src/txt/paragraph.cc
+237
-25
third_party/txt/src/txt/paragraph.h
third_party/txt/src/txt/paragraph.h
+65
-1
third_party/txt/src/txt/paragraph_builder.cc
third_party/txt/src/txt/paragraph_builder.cc
+10
-0
third_party/txt/src/txt/paragraph_builder.h
third_party/txt/src/txt/paragraph_builder.h
+18
-0
third_party/txt/src/txt/placeholder_run.cc
third_party/txt/src/txt/placeholder_run.cc
+34
-0
third_party/txt/src/txt/placeholder_run.h
third_party/txt/src/txt/placeholder_run.h
+89
-0
third_party/txt/tests/paragraph_unittests.cc
third_party/txt/tests/paragraph_unittests.cc
+1043
-0
未找到文件。
ci/licenses_golden/licenses_flutter
浏览文件 @
a4abfb23
...
...
@@ -1059,6 +1059,8 @@ FILE: ../../../flutter/third_party/txt/src/txt/paragraph_builder.cc
FILE: ../../../flutter/third_party/txt/src/txt/paragraph_builder.h
FILE: ../../../flutter/third_party/txt/src/txt/paragraph_style.cc
FILE: ../../../flutter/third_party/txt/src/txt/paragraph_style.h
FILE: ../../../flutter/third_party/txt/src/txt/placeholder_run.cc
FILE: ../../../flutter/third_party/txt/src/txt/placeholder_run.h
FILE: ../../../flutter/third_party/txt/src/txt/styled_runs.cc
FILE: ../../../flutter/third_party/txt/src/txt/styled_runs.h
FILE: ../../../flutter/third_party/txt/src/txt/test_font_manager.cc
...
...
lib/stub_ui/lib/src/ui/text.dart
浏览文件 @
a4abfb23
...
...
@@ -1195,8 +1195,9 @@ enum BoxHeightStyle {
tight
,
/// The height of the boxes will be the maximum height of all runs in the
/// line. All boxes in the same line will be the same height. This does not
/// guarantee that the boxes will cover the entire vertical height of the line
/// line. All boxes in the same line will be the same height.
///
/// This does not guarantee that the boxes will cover the entire vertical height of the line
/// when there is additional line spacing.
///
/// See [RectHeightStyle.includeLineSpacingTop], [RectHeightStyle.includeLineSpacingMiddle],
...
...
@@ -1242,12 +1243,57 @@ enum BoxWidthStyle {
/// Adds up to two additional boxes as needed at the beginning and/or end
/// of each line so that the widths of the boxes in line are the same width
/// as the widest line in the paragraph. The additional boxes on each line
/// are only added when the relevant box at the relevant edge of that line
/// does not span the maximum width of the paragraph.
/// as the widest line in the paragraph.
///
/// The additional boxes on each line are only added when the relevant box
/// at the relevant edge of that line does not span the maximum width of
/// the paragraph.
max
,
}
/// Where to vertically align the placeholder relative to the surrounding text.
///
/// Used by [ParagraphBuilder.addPlaceholder].
enum
PlaceholderAlignment
{
/// Match the baseline of the placeholder with the baseline.
///
/// The [TextBaseline] to use must be specified and non-null when using this
/// alignment mode.
baseline
,
/// Align the bottom edge of the placeholder with the baseline such that the
/// placeholder sits on top of the baseline.
///
/// The [TextBaseline] to use must be specified and non-null when using this
/// alignment mode.
aboveBaseline
,
/// Align the top edge of the placeholder with the baseline specified
/// such that the placeholder hangs below the baseline.
///
/// The [TextBaseline] to use must be specified and non-null when using this
/// alignment mode.
belowBaseline
,
/// Align the top edge of the placeholder with the top edge of the font.
///
/// When the placeholder is very tall, the extra space will hang from
/// the top and extend through the bottom of the line.
top
,
/// Align the bottom edge of the placeholder with the top edge of the font.
///
/// When the placeholder is very tall, the extra space will rise from the
/// bottom and extend through the top of the line.
bottom
,
/// Align the middle of the placeholder with the middle of the text.
///
/// When the placeholder is very tall, the extra space will grow equally
/// from the top and bottom of the line.
middle
,
}
/// A paragraph of text.
///
/// A paragraph retains the size and position of each glyph in the text and can
...
...
@@ -1490,6 +1536,9 @@ class Paragraph {
/// parameters default to the tight option, which will provide close-fitting
/// boxes and will not account for any line spacing.
///
/// Coordinates of the TextBox are relative to the upper-left corner of the paragraph,
/// where positive y values indicate down.
///
/// The [boxHeightStyle] and [boxWidthStyle] parameters must not be null.
///
/// See [BoxHeightStyle] and [BoxWidthStyle] for full descriptions of each option.
...
...
@@ -1536,6 +1585,17 @@ class Paragraph {
);
}
/// Returns a list of text boxes that enclose all placeholders in the paragraph.
///
/// The order of the boxes are in the same order as passed in through [addPlaceholder].
///
/// Coordinates of the [TextBox] are relative to the upper-left corner of the paragraph,
/// where positive y values indicate down.
List
<
TextBox
>
getBoxesForPlaceholders
()
{
// TODO(garyq): Implement stub_ui version of this.
throw
UnimplementedError
();
}
/// Returns the text position closest to the given offset.
///
/// It does so by performing a binary search to find where the tap occurred
...
...
@@ -1628,6 +1688,7 @@ class ParagraphBuilder {
/// [Paragraph].
ParagraphBuilder
(
ParagraphStyle
style
)
:
_paragraphStyle
=
style
{
// TODO(b/128317744): Implement support for strut font families.
_placeholderCount
=
0
;
List
<
String
>
strutFontFamilies
;
if
(
style
.
_strutStyle
!=
null
)
{
strutFontFamilies
=
<
String
>[];
...
...
@@ -1642,6 +1703,14 @@ class ParagraphBuilder {
element:
_paragraphElement
,
style:
_paragraphStyle
);
}
/// The number of placeholders currently in the paragraph.
int
get
placeholderCount
=>
_placeholderCount
;
int
_placeholderCount
;
/// The scales of the placeholders in the paragraph.
List
<
double
>
get
placeholderScales
=>
_placeholderScales
;
List
<
double
>
_placeholderScales
=
<
double
>[];
/// Applies the given style to the added text until [pop] is called.
///
/// See [pop] for details.
...
...
@@ -1650,7 +1719,7 @@ class ParagraphBuilder {
}
// TODO(yjbanov): do we need to do this?
// static String _encodeLocale(Locale locale) => locale?.toString() ?? '';
// static String _encodeLocale(Locale locale) => locale?.toString() ?? '';
/// Ends the effect of the most recent call to [pushStyle].
///
...
...
@@ -1669,6 +1738,58 @@ class ParagraphBuilder {
_ops
.
add
(
text
);
}
/// Adds an inline placeholder space to the paragraph.
///
/// The paragraph will contain a rectangular space with no text of the dimensions
/// specified.
///
/// The `width` and `height` parameters specify the size of the placeholder rectangle.
///
/// The `alignment` parameter specifies how the placeholder rectangle will be vertically
/// aligned with the surrounding text. When [PlaceholderAlignment.baseline],
/// [PlaceholderAlignment.aboveBaseline], and [PlaceholderAlignment.belowBaseline]
/// alignment modes are used, the baseline needs to be set with the `baseline`.
/// When using [PlaceholderAlignment.baseline], `baselineOffset` indicates the distance
/// of the baseline down from the top of of the rectangle. The default `baselineOffset`
/// is the `height`.
///
/// Examples:
///
/// * For a 30x50 placeholder with the bottom edge aligned with the bottom of the text, use:
/// `addPlaceholder(30, 50, PlaceholderAlignment.bottom);`
/// * For a 30x50 placeholder that is vertically centered around the text, use:
/// `addPlaceholder(30, 50, PlaceholderAlignment.middle);`.
/// * For a 30x50 placeholder that sits completely on top of the alphabetic baseline, use:
/// `addPlaceholder(30, 50, PlaceholderAlignment.aboveBaseline, baseline: TextBaseline.alphabetic)`.
/// * For a 30x50 placeholder with 40 pixels above and 10 pixels below the alphabetic baseline, use:
/// `addPlaceholder(30, 50, PlaceholderAlignment.baseline, baseline: TextBaseline.alphabetic, baselineOffset: 40)`.
///
/// Lines are permitted to break around each placeholder.
///
/// Decorations will be drawn based on the font defined in the most recently
/// pushed [TextStyle]. The decorations are drawn as if unicode text were present
/// in the placeholder space, and will draw the same regardless of the height and
/// alignment of the placeholder. To hide or manually adjust decorations to fit,
/// a text style with the desired decoration behavior should be pushed before
/// adding a placeholder.
///
/// Any decorations drawn through a placeholder will exist on the same canvas/layer
/// as the text. This means any content drawn on top of the space reserved by
/// the placeholder will be drawn over the decoration, possibly obscuring the
/// decoration.
///
/// Placeholders are represented by a unicode 0xFFFC "object replacement character"
/// in the text buffer. For each placeholder, one object replacement character is
/// added on to the text buffer.
void
addPlaceholder
(
double
width
,
double
height
,
PlaceholderAlignment
alignment
,
{
double
scale
,
double
baselineOffset
,
TextBaseline
baseline
,
})
{
// TODO(garyq): Implement stub_ui version of this.
throw
UnimplementedError
();
}
/// Applies the given paragraph style and returns a [Paragraph] containing the
/// added text and associated styling.
///
...
...
lib/ui/text.dart
浏览文件 @
a4abfb23
...
...
@@ -1381,72 +1381,116 @@ class ParagraphConstraints {
/// Defines various ways to vertically bound the boxes returned by
/// [Paragraph.getBoxesForRange].
enum
BoxHeightStyle
{
/// Provide tight bounding boxes that fit heights per run. This style may result
/// in uneven bounding boxes that do not nicely connect with adjacent boxes.
tight
,
/// The height of the boxes will be the maximum height of all runs in the
/// line. All boxes in the same line will be the same height. This does not
/// guarantee that the boxes will cover the entire vertical height of the line
/// when there is additional line spacing.
///
/// See [RectHeightStyle.includeLineSpacingTop], [RectHeightStyle.includeLineSpacingMiddle],
/// and [RectHeightStyle.includeLineSpacingBottom] for styles that will cover
/// the entire line.
max
,
/// Extends the top and bottom edge of the bounds to fully cover any line
/// spacing.
///
/// The top and bottom of each box will cover half of the
/// space above and half of the space below the line.
///
/// {@template flutter.dart:ui.boxHeightStyle.includeLineSpacing}
/// The top edge of each line should be the same as the bottom edge
/// of the line above. There should be no gaps in vertical coverage given any
/// amount of line spacing. Line spacing is not included above the first line
/// and below the last line due to no additional space present there.
/// {@endtemplate}
includeLineSpacingMiddle
,
/// Extends the top edge of the bounds to fully cover any line spacing.
///
/// The line spacing will be added to the top of the box.
///
/// {@macro flutter.dart:ui.rectHeightStyle.includeLineSpacing}
includeLineSpacingTop
,
/// Extends the bottom edge of the bounds to fully cover any line spacing.
///
/// The line spacing will be added to the bottom of the box.
///
/// {@macro flutter.dart:ui.boxHeightStyle.includeLineSpacing}
includeLineSpacingBottom
,
/// Calculate box heights based on the metrics of this paragraph's [StrutStyle].
///
/// Boxes based on the strut will have consistent heights throughout the
/// entire paragraph. The top edge of each line will align with the bottom
/// edge of the previous line. It is possible for glyphs to extend outside
/// these boxes.
///
/// Will fall back to tight bounds if the strut is disabled or invalid.
strut
,
/// Provide tight bounding boxes that fit heights per run. This style may result
/// in uneven bounding boxes that do not nicely connect with adjacent boxes.
tight
,
/// The height of the boxes will be the maximum height of all runs in the
/// line. All boxes in the same line will be the same height.
///
/// This does not guarantee that the boxes will cover the entire vertical height of the line
/// when there is additional line spacing.
///
/// See [RectHeightStyle.includeLineSpacingTop], [RectHeightStyle.includeLineSpacingMiddle],
/// and [RectHeightStyle.includeLineSpacingBottom] for styles that will cover
/// the entire line.
max
,
/// Extends the top and bottom edge of the bounds to fully cover any line
/// spacing.
///
/// The top and bottom of each box will cover half of the
/// space above and half of the space below the line.
///
/// {@template flutter.dart:ui.boxHeightStyle.includeLineSpacing}
/// The top edge of each line should be the same as the bottom edge
/// of the line above. There should be no gaps in vertical coverage given any
/// amount of line spacing. Line spacing is not included above the first line
/// and below the last line due to no additional space present there.
/// {@endtemplate}
includeLineSpacingMiddle
,
/// Extends the top edge of the bounds to fully cover any line spacing.
///
/// The line spacing will be added to the top of the box.
///
/// {@macro flutter.dart:ui.rectHeightStyle.includeLineSpacing}
includeLineSpacingTop
,
/// Extends the bottom edge of the bounds to fully cover any line spacing.
///
/// The line spacing will be added to the bottom of the box.
///
/// {@macro flutter.dart:ui.boxHeightStyle.includeLineSpacing}
includeLineSpacingBottom
,
/// Calculate box heights based on the metrics of this paragraph's [StrutStyle].
///
/// Boxes based on the strut will have consistent heights throughout the
/// entire paragraph. The top edge of each line will align with the bottom
/// edge of the previous line. It is possible for glyphs to extend outside
/// these boxes.
strut
,
}
/// Defines various ways to horizontally bound the boxes returned by
/// [Paragraph.getBoxesForRange].
enum
BoxWidthStyle
{
// Provide tight bounding boxes that fit widths to the runs of each line
// independently.
tight
,
/// Adds up to two additional boxes as needed at the beginning and/or end
/// of each line so that the widths of the boxes in line are the same width
/// as the widest line in the paragraph. The additional boxes on each line
/// are only added when the relevant box at the relevant edge of that line
/// does not span the maximum width of the paragraph.
max
,
// Provide tight bounding boxes that fit widths to the runs of each line
// independently.
tight
,
/// Adds up to two additional boxes as needed at the beginning and/or end
/// of each line so that the widths of the boxes in line are the same width
/// as the widest line in the paragraph.
///
/// The additional boxes on each line are only added when the relevant box
/// at the relevant edge of that line does not span the maximum width of
/// the paragraph.
max
,
}
/// Where to vertically align the placeholder relative to the surrounding text.
///
/// Used by [ParagraphBuilder.addPlaceholder].
enum
PlaceholderAlignment
{
/// Match the baseline of the placeholder with the baseline.
///
/// The [TextBaseline] to use must be specified and non-null when using this
/// alignment mode.
baseline
,
/// Align the bottom edge of the placeholder with the baseline such that the
/// placeholder sits on top of the baseline.
///
/// The [TextBaseline] to use must be specified and non-null when using this
/// alignment mode.
aboveBaseline
,
/// Align the top edge of the placeholder with the baseline specified
/// such that the placeholder hangs below the baseline.
///
/// The [TextBaseline] to use must be specified and non-null when using this
/// alignment mode.
belowBaseline
,
/// Align the top edge of the placeholder with the top edge of the font.
///
/// When the placeholder is very tall, the extra space will hang from
/// the top and extend through the bottom of the line.
top
,
/// Align the bottom edge of the placeholder with the top edge of the font.
///
/// When the placeholder is very tall, the extra space will rise from the
/// bottom and extend through the top of the line.
bottom
,
/// Align the middle of the placeholder with the middle of the text.
///
/// When the placeholder is very tall, the extra space will grow equally
/// from the top and bottom of the line.
middle
,
}
/// A paragraph of text.
...
...
@@ -1525,6 +1569,9 @@ class Paragraph extends NativeFieldWrapperClass2 {
/// parameters default to the tight option, which will provide close-fitting
/// boxes and will not account for any line spacing.
///
/// Coordinates of the TextBox are relative to the upper-left corner of the paragraph,
/// where positive y values indicate down.
///
/// The [boxHeightStyle] and [boxWidthStyle] parameters must not be null.
///
/// See [BoxHeightStyle] and [BoxWidthStyle] for full descriptions of each option.
...
...
@@ -1533,9 +1580,16 @@ class Paragraph extends NativeFieldWrapperClass2 {
assert
(
boxWidthStyle
!=
null
);
return
_getBoxesForRange
(
start
,
end
,
boxHeightStyle
.
index
,
boxWidthStyle
.
index
);
}
List
<
TextBox
>
_getBoxesForRange
(
int
start
,
int
end
,
int
boxHeightStyle
,
int
boxWidthStyle
)
native
'Paragraph_getRectsForRange'
;
/// Returns a list of text boxes that enclose all placeholders in the paragraph.
///
/// The order of the boxes are in the same order as passed in through [addPlaceholder].
///
/// Coordinates of the [TextBox] are relative to the upper-left corner of the paragraph,
/// where positive y values indicate down.
List
<
TextBox
>
getBoxesForPlaceholders
()
native
'Paragraph_getRectsForPlaceholders'
;
/// Returns the text position closest to the given offset.
TextPosition
getPositionForOffset
(
Offset
offset
)
{
final
List
<
int
>
encoded
=
_getPositionForOffset
(
offset
.
dx
,
offset
.
dy
);
...
...
@@ -1576,6 +1630,7 @@ class ParagraphBuilder extends NativeFieldWrapperClass2 {
/// [Paragraph].
@pragma
(
'vm:entry-point'
)
ParagraphBuilder
(
ParagraphStyle
style
)
{
_placeholderCount
=
0
;
List
<
String
>
strutFontFamilies
;
if
(
style
.
_strutStyle
!=
null
)
{
strutFontFamilies
=
<
String
>[];
...
...
@@ -1607,6 +1662,14 @@ class ParagraphBuilder extends NativeFieldWrapperClass2 {
String
locale
)
native
'ParagraphBuilder_constructor'
;
/// The number of placeholders currently in the paragraph.
int
get
placeholderCount
=>
_placeholderCount
;
int
_placeholderCount
;
/// The scales of the placeholders in the paragraph.
List
<
double
>
get
placeholderScales
=>
_placeholderScales
;
List
<
double
>
_placeholderScales
=
<
double
>[];
/// Applies the given style to the added text until [pop] is called.
///
/// See [pop] for details.
...
...
@@ -1682,6 +1745,71 @@ class ParagraphBuilder extends NativeFieldWrapperClass2 {
}
String
_addText
(
String
text
)
native
'ParagraphBuilder_addText'
;
/// Adds an inline placeholder space to the paragraph.
///
/// The paragraph will contain a rectangular space with no text of the dimensions
/// specified.
///
/// The `width` and `height` parameters specify the size of the placeholder rectangle.
///
/// The `alignment` parameter specifies how the placeholder rectangle will be vertically
/// aligned with the surrounding text. When [PlaceholderAlignment.baseline],
/// [PlaceholderAlignment.aboveBaseline], and [PlaceholderAlignment.belowBaseline]
/// alignment modes are used, the baseline needs to be set with the `baseline`.
/// When using [PlaceholderAlignment.baseline], `baselineOffset` indicates the distance
/// of the baseline down from the top of of the rectangle. The default `baselineOffset`
/// is the `height`.
///
/// Examples:
///
/// * For a 30x50 placeholder with the bottom edge aligned with the bottom of the text, use:
/// `addPlaceholder(30, 50, PlaceholderAlignment.bottom);`
/// * For a 30x50 placeholder that is vertically centered around the text, use:
/// `addPlaceholder(30, 50, PlaceholderAlignment.middle);`.
/// * For a 30x50 placeholder that sits completely on top of the alphabetic baseline, use:
/// `addPlaceholder(30, 50, PlaceholderAlignment.aboveBaseline, baseline: TextBaseline.alphabetic)`.
/// * For a 30x50 placeholder with 40 pixels above and 10 pixels below the alphabetic baseline, use:
/// `addPlaceholder(30, 50, PlaceholderAlignment.baseline, baseline: TextBaseline.alphabetic, baselineOffset: 40)`.
///
/// Lines are permitted to break around each placeholder.
///
/// Decorations will be drawn based on the font defined in the most recently
/// pushed [TextStyle]. The decorations are drawn as if unicode text were present
/// in the placeholder space, and will draw the same regardless of the height and
/// alignment of the placeholder. To hide or manually adjust decorations to fit,
/// a text style with the desired decoration behavior should be pushed before
/// adding a placeholder.
///
/// Any decorations drawn through a placeholder will exist on the same canvas/layer
/// as the text. This means any content drawn on top of the space reserved by
/// the placeholder will be drawn over the decoration, possibly obscuring the
/// decoration.
///
/// Placeholders are represented by a unicode 0xFFFC "object replacement character"
/// in the text buffer. For each placeholder, one object replacement character is
/// added on to the text buffer.
///
/// The `scale` parameter will scale the `width` and `height` by the specified amount,
/// and keep track of the scale. The scales of placeholders added can be accessed
/// through [placeholderScales]. This is primarily used for acessibility scaling.
void
addPlaceholder
(
double
width
,
double
height
,
PlaceholderAlignment
alignment
,
{
double
scale
=
1.0
,
double
baselineOffset
,
TextBaseline
baseline
,
})
{
// Require a baseline to be specified if using a baseline-based alignment.
assert
((
alignment
==
PlaceholderAlignment
.
aboveBaseline
||
alignment
==
PlaceholderAlignment
.
belowBaseline
||
alignment
==
PlaceholderAlignment
.
baseline
)
?
baseline
!=
null
:
true
);
// Default the baselineOffset to height if null. This will place the placeholder
// fully above the baseline, similar to [PlaceholderAlignment.aboveBaseline].
baselineOffset
=
baselineOffset
??
height
;
_addPlaceholder
(
width
*
scale
,
height
*
scale
,
alignment
.
index
,
(
baselineOffset
==
null
?
height
:
baselineOffset
)
*
scale
,
baseline
==
null
?
null
:
baseline
.
index
);
_placeholderCount
++;
_placeholderScales
.
add
(
scale
);
}
String
_addPlaceholder
(
double
width
,
double
height
,
int
alignment
,
double
baselineOffset
,
int
baseline
)
native
'ParagraphBuilder_addPlaceholder'
;
/// Applies the given paragraph style and returns a [Paragraph] containing the
/// added text and associated styling.
///
...
...
lib/ui/text/paragraph.cc
浏览文件 @
a4abfb23
...
...
@@ -19,19 +19,20 @@ namespace flutter {
IMPLEMENT_WRAPPERTYPEINFO
(
ui
,
Paragraph
);
#define FOR_EACH_BINDING(V) \
V(Paragraph, width) \
V(Paragraph, height) \
V(Paragraph, longestLine) \
V(Paragraph, minIntrinsicWidth) \
V(Paragraph, maxIntrinsicWidth) \
V(Paragraph, alphabeticBaseline) \
V(Paragraph, ideographicBaseline) \
V(Paragraph, didExceedMaxLines) \
V(Paragraph, layout) \
V(Paragraph, paint) \
V(Paragraph, getWordBoundary) \
V(Paragraph, getRectsForRange) \
#define FOR_EACH_BINDING(V) \
V(Paragraph, width) \
V(Paragraph, height) \
V(Paragraph, longestLine) \
V(Paragraph, minIntrinsicWidth) \
V(Paragraph, maxIntrinsicWidth) \
V(Paragraph, alphabeticBaseline) \
V(Paragraph, ideographicBaseline) \
V(Paragraph, didExceedMaxLines) \
V(Paragraph, layout) \
V(Paragraph, paint) \
V(Paragraph, getWordBoundary) \
V(Paragraph, getRectsForRange) \
V(Paragraph, getRectsForPlaceholders) \
V(Paragraph, getPositionForOffset)
DART_BIND_ALL
(
Paragraph
,
FOR_EACH_BINDING
)
...
...
@@ -98,6 +99,10 @@ std::vector<TextBox> Paragraph::getRectsForRange(unsigned start,
static_cast
<
txt
::
Paragraph
::
RectWidthStyle
>
(
boxWidthStyle
));
}
std
::
vector
<
TextBox
>
Paragraph
::
getRectsForPlaceholders
()
{
return
m_paragraphImpl
->
getRectsForPlaceholders
();
}
Dart_Handle
Paragraph
::
getPositionForOffset
(
double
dx
,
double
dy
)
{
return
m_paragraphImpl
->
getPositionForOffset
(
dx
,
dy
);
}
...
...
lib/ui/text/paragraph.h
浏览文件 @
a4abfb23
...
...
@@ -47,6 +47,7 @@ class Paragraph : public RefCountedDartWrappable<Paragraph> {
unsigned
end
,
unsigned
boxHeightStyle
,
unsigned
boxWidthStyle
);
std
::
vector
<
TextBox
>
getRectsForPlaceholders
();
Dart_Handle
getPositionForOffset
(
double
dx
,
double
dy
);
Dart_Handle
getWordBoundary
(
unsigned
offset
);
...
...
lib/ui/text/paragraph_builder.cc
浏览文件 @
a4abfb23
...
...
@@ -14,6 +14,7 @@
#include "flutter/third_party/txt/src/txt/font_style.h"
#include "flutter/third_party/txt/src/txt/font_weight.h"
#include "flutter/third_party/txt/src/txt/paragraph_style.h"
#include "flutter/third_party/txt/src/txt/text_baseline.h"
#include "flutter/third_party/txt/src/txt/text_decoration.h"
#include "flutter/third_party/txt/src/txt/text_style.h"
#include "third_party/icu/source/common/unicode/ustring.h"
...
...
@@ -132,10 +133,11 @@ static void ParagraphBuilder_constructor(Dart_NativeArguments args) {
IMPLEMENT_WRAPPERTYPEINFO
(
ui
,
ParagraphBuilder
);
#define FOR_EACH_BINDING(V) \
V(ParagraphBuilder, pushStyle) \
V(ParagraphBuilder, pop) \
V(ParagraphBuilder, addText) \
#define FOR_EACH_BINDING(V) \
V(ParagraphBuilder, pushStyle) \
V(ParagraphBuilder, pop) \
V(ParagraphBuilder, addText) \
V(ParagraphBuilder, addPlaceholder) \
V(ParagraphBuilder, build)
FOR_EACH_BINDING
(
DART_NATIVE_CALLBACK
)
...
...
@@ -459,6 +461,20 @@ Dart_Handle ParagraphBuilder::addText(const std::u16string& text) {
return
Dart_Null
();
}
Dart_Handle
ParagraphBuilder
::
addPlaceholder
(
double
width
,
double
height
,
unsigned
alignment
,
double
baseline_offset
,
unsigned
baseline
)
{
txt
::
PlaceholderRun
placeholder_run
(
width
,
height
,
static_cast
<
txt
::
PlaceholderAlignment
>
(
alignment
),
static_cast
<
txt
::
TextBaseline
>
(
baseline
),
baseline_offset
);
m_paragraphBuilder
->
AddPlaceholder
(
placeholder_run
);
return
Dart_Null
();
}
fml
::
RefPtr
<
Paragraph
>
ParagraphBuilder
::
build
()
{
return
Paragraph
::
Create
(
m_paragraphBuilder
->
Build
());
}
...
...
lib/ui/text/paragraph_builder.h
浏览文件 @
a4abfb23
...
...
@@ -6,6 +6,7 @@
#define FLUTTER_LIB_UI_TEXT_PARAGRAPH_BUILDER_H_
#include <memory>
#include "flutter/lib/ui/dart_wrapper.h"
#include "flutter/lib/ui/painting/paint.h"
#include "flutter/lib/ui/text/paragraph.h"
...
...
@@ -56,6 +57,18 @@ class ParagraphBuilder : public RefCountedDartWrappable<ParagraphBuilder> {
Dart_Handle
addText
(
const
std
::
u16string
&
text
);
// Pushes the information requried to leave an open space, where Flutter may
// draw a custom placeholder into.
//
// Internally, this method adds a single object replacement character (0xFFFC)
// and emplaces a new PlaceholderRun instance to the vector of inline
// placeholders.
Dart_Handle
addPlaceholder
(
double
width
,
double
height
,
unsigned
alignment
,
double
baseline_offset
,
unsigned
baseline
);
fml
::
RefPtr
<
Paragraph
>
build
();
static
void
RegisterNatives
(
tonic
::
DartLibraryNatives
*
natives
);
...
...
lib/ui/text/paragraph_impl.h
浏览文件 @
a4abfb23
...
...
@@ -41,6 +41,8 @@ class ParagraphImpl {
txt
::
Paragraph
::
RectHeightStyle
rect_height_style
,
txt
::
Paragraph
::
RectWidthStyle
rect_width_style
)
=
0
;
virtual
std
::
vector
<
TextBox
>
getRectsForPlaceholders
()
=
0
;
virtual
Dart_Handle
getPositionForOffset
(
double
dx
,
double
dy
)
=
0
;
virtual
Dart_Handle
getWordBoundary
(
unsigned
offset
)
=
0
;
...
...
lib/ui/text/paragraph_impl_txt.cc
浏览文件 @
a4abfb23
...
...
@@ -79,6 +79,17 @@ std::vector<TextBox> ParagraphImplTxt::getRectsForRange(
return
result
;
}
std
::
vector
<
TextBox
>
ParagraphImplTxt
::
getRectsForPlaceholders
()
{
std
::
vector
<
TextBox
>
result
;
std
::
vector
<
txt
::
Paragraph
::
TextBox
>
boxes
=
m_paragraph
->
GetRectsForPlaceholders
();
for
(
const
txt
::
Paragraph
::
TextBox
&
box
:
boxes
)
{
result
.
emplace_back
(
box
.
rect
,
static_cast
<
flutter
::
TextDirection
>
(
box
.
direction
));
}
return
result
;
}
Dart_Handle
ParagraphImplTxt
::
getPositionForOffset
(
double
dx
,
double
dy
)
{
Dart_Handle
result
=
Dart_NewListOf
(
Dart_CoreType_Int
,
2
);
txt
::
Paragraph
::
PositionWithAffinity
pos
=
...
...
lib/ui/text/paragraph_impl_txt.h
浏览文件 @
a4abfb23
...
...
@@ -34,6 +34,7 @@ class ParagraphImplTxt : public ParagraphImpl {
unsigned
end
,
txt
::
Paragraph
::
RectHeightStyle
rect_height_style
,
txt
::
Paragraph
::
RectWidthStyle
rect_width_style
)
override
;
std
::
vector
<
TextBox
>
getRectsForPlaceholders
()
override
;
Dart_Handle
getPositionForOffset
(
double
dx
,
double
dy
)
override
;
Dart_Handle
getWordBoundary
(
unsigned
offset
)
override
;
...
...
third_party/txt/BUILD.gn
浏览文件 @
a4abfb23
...
...
@@ -95,6 +95,8 @@ source_set("txt") {
"src/txt/paragraph_builder.h",
"src/txt/paragraph_style.cc",
"src/txt/paragraph_style.h",
"src/txt/placeholder_run.cc",
"src/txt/placeholder_run.h",
"src/txt/platform.h",
"src/txt/styled_runs.cc",
"src/txt/styled_runs.h",
...
...
third_party/txt/src/minikin/LineBreaker.cpp
浏览文件 @
a4abfb23
...
...
@@ -356,6 +356,14 @@ void LineBreaker::pushBreak(int offset, float width, uint8_t hyphenEdit) {
mFirstTabIndex
=
INT_MAX
;
}
// libtxt: Add ability to set custom char widths. This allows manual definition
// of the widths of arbitrary glyphs. To linebreak properly, call addStyleRun
// with nullptr as the paint property, which will lead it to assume the width
// has already been calculated. Used for properly breaking inline widgets.
void
LineBreaker
::
setCustomCharWidth
(
size_t
offset
,
float
width
)
{
mCharWidths
[
offset
]
=
(
width
);
}
void
LineBreaker
::
addReplacement
(
size_t
start
,
size_t
end
,
float
width
)
{
mCharWidths
[
start
]
=
width
;
std
::
fill
(
&
mCharWidths
[
start
+
1
],
&
mCharWidths
[
end
],
0.0
f
);
...
...
third_party/txt/src/minikin/LineBreaker.h
浏览文件 @
a4abfb23
...
...
@@ -149,6 +149,13 @@ class LineBreaker {
size_t
computeBreaks
();
// libtxt: Add ability to set custom char widths. This allows manual
// definition of the widths of arbitrary glyphs. To linebreak properly, call
// addStyleRun with nullptr as the paint property, which will lead it to
// assume the width has already been calculated. Used for properly breaking
// inline placeholders.
void
setCustomCharWidth
(
size_t
offset
,
float
width
);
const
int
*
getBreaks
()
const
{
return
mBreaks
.
data
();
}
const
float
*
getWidths
()
const
{
return
mWidths
.
data
();
}
...
...
third_party/txt/src/txt/paint_record.cc
浏览文件 @
a4abfb23
...
...
@@ -15,6 +15,7 @@
*/
#include "paint_record.h"
#include "flutter/fml/logging.h"
namespace
txt
{
...
...
@@ -38,6 +39,25 @@ PaintRecord::PaintRecord(TextStyle style,
x_end_
(
x_end
),
is_ghost_
(
is_ghost
)
{}
PaintRecord
::
PaintRecord
(
TextStyle
style
,
SkPoint
offset
,
sk_sp
<
SkTextBlob
>
text
,
SkFontMetrics
metrics
,
size_t
line
,
double
x_start
,
double
x_end
,
bool
is_ghost
,
PlaceholderRun
*
placeholder_run
)
:
style_
(
style
),
offset_
(
offset
),
text_
(
std
::
move
(
text
)),
metrics_
(
metrics
),
line_
(
line
),
x_start_
(
x_start
),
x_end_
(
x_end
),
is_ghost_
(
is_ghost
),
placeholder_run_
(
placeholder_run
)
{}
PaintRecord
::
PaintRecord
(
TextStyle
style
,
sk_sp
<
SkTextBlob
>
text
,
SkFontMetrics
metrics
,
...
...
@@ -59,6 +79,7 @@ PaintRecord::PaintRecord(PaintRecord&& other) {
text_
=
std
::
move
(
other
.
text_
);
metrics_
=
other
.
metrics_
;
line_
=
other
.
line_
;
placeholder_run_
=
other
.
placeholder_run_
;
x_start_
=
other
.
x_start_
;
x_end_
=
other
.
x_end_
;
is_ghost_
=
other
.
is_ghost_
;
...
...
@@ -73,6 +94,7 @@ PaintRecord& PaintRecord::operator=(PaintRecord&& other) {
x_start_
=
other
.
x_start_
;
x_end_
=
other
.
x_end_
;
is_ghost_
=
other
.
is_ghost_
;
placeholder_run_
=
other
.
placeholder_run_
;
return
*
this
;
}
...
...
third_party/txt/src/txt/paint_record.h
浏览文件 @
a4abfb23
...
...
@@ -19,6 +19,7 @@
#include "flutter/fml/logging.h"
#include "flutter/fml/macros.h"
#include "placeholder_run.h"
#include "text_style.h"
#include "third_party/skia/include/core/SkFontMetrics.h"
#include "third_party/skia/include/core/SkTextBlob.h"
...
...
@@ -43,6 +44,16 @@ class PaintRecord {
double
x_end
,
bool
is_ghost
);
PaintRecord
(
TextStyle
style
,
SkPoint
offset
,
sk_sp
<
SkTextBlob
>
text
,
SkFontMetrics
metrics
,
size_t
line
,
double
x_start
,
double
x_end
,
bool
is_ghost
,
PlaceholderRun
*
placeholder_run
);
PaintRecord
(
TextStyle
style
,
sk_sp
<
SkTextBlob
>
text
,
SkFontMetrics
metrics
,
...
...
@@ -71,8 +82,12 @@ class PaintRecord {
double
x_end
()
const
{
return
x_end_
;
}
double
GetRunWidth
()
const
{
return
x_end_
-
x_start_
;
}
PlaceholderRun
*
GetPlaceholderRun
()
const
{
return
placeholder_run_
;
}
bool
isGhost
()
const
{
return
is_ghost_
;
}
bool
isPlaceholder
()
const
{
return
placeholder_run_
==
nullptr
;
}
private:
TextStyle
style_
;
// offset_ is the overall offset of the origin of the SkTextBlob.
...
...
@@ -87,6 +102,10 @@ class PaintRecord {
// 'Ghost' runs represent trailing whitespace. 'Ghost' runs should not have
// decorations painted on them and do not impact layout of visible glyphs.
bool
is_ghost_
=
false
;
// Stores the corresponding PlaceholderRun that the record corresponds to.
// When this is nullptr, then the record is of normal text and does not
// represent an inline placeholder.
PlaceholderRun
*
placeholder_run_
=
nullptr
;
FML_DISALLOW_COPY_AND_ASSIGN
(
PaintRecord
);
};
...
...
third_party/txt/src/txt/paragraph.cc
浏览文件 @
a4abfb23
...
...
@@ -209,13 +209,15 @@ Paragraph::CodeUnitRun::CodeUnitRun(std::vector<GlyphPosition>&& p,
Range
<
double
>
x
,
size_t
line
,
const
SkFontMetrics
&
metrics
,
TextDirection
dir
)
TextDirection
dir
,
const
PlaceholderRun
*
placeholder
)
:
positions
(
std
::
move
(
p
)),
code_units
(
cu
),
x_pos
(
x
),
line_number
(
line
),
font_metrics
(
metrics
),
direction
(
dir
)
{}
direction
(
dir
),
placeholder_run
(
placeholder
)
{}
void
Paragraph
::
CodeUnitRun
::
Shift
(
double
delta
)
{
x_pos
.
Shift
(
delta
);
...
...
@@ -237,21 +239,33 @@ void Paragraph::SetText(std::vector<uint16_t> text, StyledRuns runs) {
runs_
=
std
::
move
(
runs
);
}
void
Paragraph
::
SetInlinePlaceholders
(
std
::
vector
<
PlaceholderRun
>
inline_placeholders
,
std
::
unordered_set
<
size_t
>
obj_replacement_char_indexes
)
{
needs_layout_
=
true
;
inline_placeholders_
=
std
::
move
(
inline_placeholders
);
obj_replacement_char_indexes_
=
std
::
move
(
obj_replacement_char_indexes
);
}
bool
Paragraph
::
ComputeLineBreaks
()
{
line_ranges_
.
clear
();
line_widths_
.
clear
();
max_intrinsic_width_
=
0
;
std
::
vector
<
size_t
>
newline_positions
;
// Discover and add all hard breaks.
for
(
size_t
i
=
0
;
i
<
text_
.
size
();
++
i
)
{
ULineBreak
ulb
=
static_cast
<
ULineBreak
>
(
u_getIntPropertyValue
(
text_
[
i
],
UCHAR_LINE_BREAK
));
if
(
ulb
==
U_LB_LINE_FEED
||
ulb
==
U_LB_MANDATORY_BREAK
)
newline_positions
.
push_back
(
i
);
}
// Break at the end of the paragraph.
newline_positions
.
push_back
(
text_
.
size
());
// Calculate and add any breaks due to a line being too long.
size_t
run_index
=
0
;
size_t
inline_placeholder_index
=
0
;
for
(
size_t
newline_index
=
0
;
newline_index
<
newline_positions
.
size
();
++
newline_index
)
{
size_t
block_start
=
...
...
@@ -266,6 +280,9 @@ bool Paragraph::ComputeLineBreaks() {
continue
;
}
// Setup breaker. We wait to set the line width in order to account for the
// widths of the inline placeholders, which are calcualted in the loop over
// the runs.
breaker_
.
setLineWidths
(
0.0
f
,
0
,
width_
);
breaker_
.
setJustified
(
paragraph_style_
.
text_align
==
TextAlign
::
justify
);
breaker_
.
setStrategy
(
paragraph_style_
.
break_strategy
);
...
...
@@ -301,15 +318,38 @@ bool Paragraph::ComputeLineBreaks() {
size_t
run_start
=
std
::
max
(
run
.
start
,
block_start
)
-
block_start
;
size_t
run_end
=
std
::
min
(
run
.
end
,
block_end
)
-
block_start
;
bool
isRtl
=
(
paragraph_style_
.
text_direction
==
TextDirection
::
rtl
);
double
run_width
=
breaker_
.
addStyleRun
(
&
paint
,
collection
,
font
,
run_start
,
run_end
,
isRtl
);
block_total_width
+=
run_width
;
// Check if the run is an object replacement character-only run. We should
// leave space for inline placeholder and break around it if appropriate.
if
(
run
.
end
-
run
.
start
==
1
&&
obj_replacement_char_indexes_
.
count
(
run
.
start
)
!=
0
&&
text_
[
run
.
start
]
==
objReplacementChar
&&
inline_placeholder_index
<
inline_placeholders_
.
size
())
{
// Is a inline placeholder run.
PlaceholderRun
placeholder_run
=
inline_placeholders_
[
inline_placeholder_index
];
block_total_width
+=
placeholder_run
.
width
;
// Inject custom width into minikin breaker. (Uses LibTxt-minikin
// patch).
breaker_
.
setCustomCharWidth
(
run
.
start
,
placeholder_run
.
width
);
// Called with nullptr as paint in order to use the custom widths passed
// above.
breaker_
.
addStyleRun
(
nullptr
,
collection
,
font
,
run_start
,
run_end
,
isRtl
);
inline_placeholder_index
++
;
}
else
{
// Is a regular text run.
double
run_width
=
breaker_
.
addStyleRun
(
&
paint
,
collection
,
font
,
run_start
,
run_end
,
isRtl
);
block_total_width
+=
run_width
;
}
if
(
run
.
end
>
block_end
)
break
;
run_index
++
;
}
max_intrinsic_width_
=
std
::
max
(
max_intrinsic_width_
,
block_total_width
);
size_t
breaks_count
=
breaker_
.
computeBreaks
();
...
...
@@ -480,6 +520,80 @@ void Paragraph::ComputeStrut(StrutMetrics* strut, SkFont& font) {
}
}
void
Paragraph
::
ComputePlaceholder
(
PlaceholderRun
*
placeholder_run
,
double
&
ascent
,
double
&
descent
)
{
if
(
placeholder_run
!=
nullptr
)
{
// Calculate how much to shift the ascent and descent to account
// for the baseline choice.
//
// TODO(garyq): implement for various baselines. Currently only
// supports for alphabetic and ideographic
double
baseline_adjustment
=
0
;
switch
(
placeholder_run
->
baseline
)
{
case
TextBaseline
::
kAlphabetic
:
{
baseline_adjustment
=
0
;
break
;
}
case
TextBaseline
::
kIdeographic
:
{
baseline_adjustment
=
-
descent
/
2
;
break
;
}
}
// Convert the ascent and descent from the font's to the placeholder
// rect's.
switch
(
placeholder_run
->
alignment
)
{
case
PlaceholderAlignment
::
kBaseline
:
{
ascent
=
baseline_adjustment
+
placeholder_run
->
baseline_offset
;
descent
=
-
baseline_adjustment
+
placeholder_run
->
height
-
placeholder_run
->
baseline_offset
;
break
;
}
case
PlaceholderAlignment
::
kAboveBaseline
:
{
ascent
=
baseline_adjustment
+
placeholder_run
->
height
;
descent
=
-
baseline_adjustment
;
break
;
}
case
PlaceholderAlignment
::
kBelowBaseline
:
{
descent
=
baseline_adjustment
+
placeholder_run
->
height
;
ascent
=
-
baseline_adjustment
;
break
;
}
case
PlaceholderAlignment
::
kTop
:
{
descent
=
placeholder_run
->
height
-
ascent
;
break
;
}
case
PlaceholderAlignment
::
kBottom
:
{
ascent
=
placeholder_run
->
height
-
descent
;
break
;
}
case
PlaceholderAlignment
::
kMiddle
:
{
double
mid
=
(
ascent
-
descent
)
/
2
;
ascent
=
mid
+
placeholder_run
->
height
/
2
;
descent
=
-
mid
+
placeholder_run
->
height
/
2
;
break
;
}
}
placeholder_run
->
baseline_offset
=
ascent
;
}
}
// Implementation outline:
//
// -For each line:
// -Compute Bidi runs, convert into line_runs (keeps in-line-range runs, adds
// special runs)
// -For each line_run (runs in the line):
// -Calculate ellipsis
// -Obtain font
// -layout.doLayout(...), genereates glyph blobs
// -For each glyph blob:
// -Convert glyph blobs into pixel metrics/advances
// -Store as paint records (for painting) and code unit runs (for metrics
// and boxes).
// -Apply letter spacing, alignment, justification, etc
// -Calculate line vertical layout (ascent, descent, etc)
// -Store per-line metrics
void
Paragraph
::
Layout
(
double
width
,
bool
force
)
{
double
rounded_width
=
floor
(
width
);
// Do not allow calling layout multiple times without changing anything.
...
...
@@ -508,6 +622,7 @@ void Paragraph::Layout(double width, bool force) {
line_baselines_
.
clear
();
glyph_lines_
.
clear
();
code_unit_runs_
.
clear
();
inline_placeholder_code_unit_runs_
.
clear
();
line_max_spacings_
.
clear
();
line_max_descent_
.
clear
();
line_max_ascent_
.
clear
();
...
...
@@ -527,6 +642,7 @@ void Paragraph::Layout(double width, bool force) {
size_t
line_limit
=
std
::
min
(
paragraph_style_
.
max_lines
,
line_ranges_
.
size
());
did_exceed_max_lines_
=
(
line_ranges_
.
size
()
>
paragraph_style_
.
max_lines
);
size_t
placeholder_run_index
=
0
;
for
(
size_t
line_number
=
0
;
line_number
<
line_limit
;
++
line_number
)
{
const
LineRange
&
line_range
=
line_ranges_
[
line_number
];
...
...
@@ -583,9 +699,21 @@ void Paragraph::Layout(double width, bool force) {
// Emplace a normal line run.
if
(
bidi_run
.
start
()
<
line_end_index
&&
bidi_run
.
end
()
>
line_range
.
start
)
{
line_runs
.
emplace_back
(
std
::
max
(
bidi_run
.
start
(),
line_range
.
start
),
std
::
min
(
bidi_run
.
end
(),
line_end_index
),
bidi_run
.
direction
(),
bidi_run
.
style
());
// The run is a placeholder run.
if
(
bidi_run
.
size
()
==
1
&&
text_
[
bidi_run
.
start
()]
==
objReplacementChar
&&
obj_replacement_char_indexes_
.
count
(
bidi_run
.
start
())
!=
0
&&
placeholder_run_index
<
inline_placeholders_
.
size
())
{
line_runs
.
emplace_back
(
std
::
max
(
bidi_run
.
start
(),
line_range
.
start
),
std
::
min
(
bidi_run
.
end
(),
line_end_index
),
bidi_run
.
direction
(),
bidi_run
.
style
(),
inline_placeholders_
[
placeholder_run_index
]);
placeholder_run_index
++
;
}
else
{
line_runs
.
emplace_back
(
std
::
max
(
bidi_run
.
start
(),
line_range
.
start
),
std
::
min
(
bidi_run
.
end
(),
line_end_index
),
bidi_run
.
direction
(),
bidi_run
.
style
());
}
}
// Include the ghost run after normal run if LTR
if
(
bidi_run
.
direction
()
==
TextDirection
::
ltr
&&
ghost_run
!=
nullptr
)
{
...
...
@@ -603,6 +731,7 @@ void Paragraph::Layout(double width, bool force) {
std
::
vector
<
GlyphPosition
>
line_glyph_positions
;
std
::
vector
<
CodeUnitRun
>
line_code_unit_runs
;
std
::
vector
<
CodeUnitRun
>
line_inline_placeholder_code_unit_runs
;
double
run_x_offset
=
0
;
double
justify_x_offset
=
0
;
std
::
vector
<
PaintRecord
>
paint_records
;
...
...
@@ -814,15 +943,25 @@ void Paragraph::Layout(double width, bool force) {
if
(
glyph_positions
.
empty
())
continue
;
SkFontMetrics
metrics
;
font
.
getMetrics
(
&
metrics
);
Range
<
double
>
record_x_pos
(
glyph_positions
.
front
().
x_pos
.
start
-
run_x_offset
,
glyph_positions
.
back
().
x_pos
.
end
-
run_x_offset
);
paint_records
.
emplace_back
(
run
.
style
(),
SkPoint
::
Make
(
run_x_offset
+
justify_x_offset
,
0
),
builder
.
make
(),
metrics
,
line_number
,
record_x_pos
.
start
,
record_x_pos
.
end
,
run
.
is_ghost
());
if
(
run
.
is_placeholder_run
())
{
paint_records
.
emplace_back
(
run
.
style
(),
SkPoint
::
Make
(
run_x_offset
+
justify_x_offset
,
0
),
builder
.
make
(),
metrics
,
line_number
,
record_x_pos
.
start
,
record_x_pos
.
start
+
run
.
placeholder_run
()
->
width
,
run
.
is_ghost
(),
run
.
placeholder_run
());
run_x_offset
+=
run
.
placeholder_run
()
->
width
;
}
else
{
paint_records
.
emplace_back
(
run
.
style
(),
SkPoint
::
Make
(
run_x_offset
+
justify_x_offset
,
0
),
builder
.
make
(),
metrics
,
line_number
,
record_x_pos
.
start
,
record_x_pos
.
end
,
run
.
is_ghost
());
}
justify_x_offset
+=
justify_x_offset_delta
;
line_glyph_positions
.
insert
(
line_glyph_positions
.
end
(),
...
...
@@ -840,20 +979,29 @@ void Paragraph::Layout(double width, bool force) {
std
::
move
(
code_unit_positions
),
Range
<
size_t
>
(
run
.
start
(),
run
.
end
()),
Range
<
double
>
(
glyph_positions
.
front
().
x_pos
.
start
,
glyph_positions
.
back
().
x_pos
.
end
),
line_number
,
metrics
,
run
.
direction
());
run
.
is_placeholder_run
()
?
glyph_positions
.
back
().
x_pos
.
start
+
run
.
placeholder_run
()
->
width
:
glyph_positions
.
back
().
x_pos
.
end
),
line_number
,
metrics
,
run
.
direction
(),
run
.
placeholder_run
());
if
(
run
.
is_placeholder_run
())
{
line_inline_placeholder_code_unit_runs
.
push_back
(
line_code_unit_runs
.
back
());
}
if
(
!
run
.
is_ghost
())
{
min_left_
=
std
::
min
(
min_left_
,
glyph_positions
.
front
().
x_pos
.
start
);
max_right_
=
std
::
max
(
max_right_
,
glyph_positions
.
back
().
x_pos
.
end
);
}
}
// for each in glyph_blobs
// Do not increase x offset for LTR trailing ghost runs as it should not
// impact the layout of visible glyphs. RTL tailing ghost runs have the
// advance subtracted, so we do add the advance here to reset the
// run_x_offset. We do keep the record though so GetRectsForRange() can
// find metrics for trailing spaces.
if
(
!
run
.
is_ghost
()
||
run
.
is_rtl
())
{
// if (!run.is_ghost() || run.is_rtl()) {
if
((
!
run
.
is_ghost
()
||
run
.
is_rtl
())
&&
!
run
.
is_placeholder_run
())
{
run_x_offset
+=
layout
.
getAdvance
();
}
}
// for each in line_runs
...
...
@@ -864,6 +1012,10 @@ void Paragraph::Layout(double width, bool force) {
for
(
CodeUnitRun
&
code_unit_run
:
line_code_unit_runs
)
{
code_unit_run
.
Shift
(
line_x_offset
);
}
for
(
CodeUnitRun
&
code_unit_run
:
line_inline_placeholder_code_unit_runs
)
{
code_unit_run
.
Shift
(
line_x_offset
);
}
for
(
GlyphPosition
&
position
:
line_glyph_positions
)
{
position
.
Shift
(
line_x_offset
);
}
...
...
@@ -876,28 +1028,39 @@ void Paragraph::Layout(double width, bool force) {
next_line_start
-
line_range
.
start
);
code_unit_runs_
.
insert
(
code_unit_runs_
.
end
(),
line_code_unit_runs
.
begin
(),
line_code_unit_runs
.
end
());
inline_placeholder_code_unit_runs_
.
insert
(
inline_placeholder_code_unit_runs_
.
end
(),
line_inline_placeholder_code_unit_runs
.
begin
(),
line_inline_placeholder_code_unit_runs
.
end
());
// Calculate the amount to advance in the y direction. This is done by
// computing the maximum ascent and descent with respect to the strut.
double
max_ascent
=
strut_
.
ascent
+
strut_
.
half_leading
;
double
max_descent
=
strut_
.
descent
+
strut_
.
half_leading
;
SkScalar
max_unscaled_ascent
=
0
;
double
max_unscaled_ascent
=
0
;
auto
update_line_metrics
=
[
&
](
const
SkFontMetrics
&
metrics
,
const
TextStyle
&
style
)
{
const
TextStyle
&
style
,
PlaceholderRun
*
placeholder_run
)
{
if
(
!
strut_
.
force_strut
)
{
double
ascent
=
(
-
metrics
.
fAscent
+
metrics
.
fLeading
/
2
)
*
style
.
height
;
max_ascent
=
std
::
max
(
ascent
,
max_ascent
);
double
descent
=
(
metrics
.
fDescent
+
metrics
.
fLeading
/
2
)
*
style
.
height
;
ComputePlaceholder
(
placeholder_run
,
ascent
,
descent
);
max_ascent
=
std
::
max
(
ascent
,
max_ascent
);
max_descent
=
std
::
max
(
descent
,
max_descent
);
}
max_unscaled_ascent
=
std
::
max
(
-
metrics
.
fAscent
,
max_unscaled_ascent
);
max_unscaled_ascent
=
std
::
max
(
placeholder_run
==
nullptr
?
-
metrics
.
fAscent
:
placeholder_run
->
baseline_offset
,
max_unscaled_ascent
);
};
for
(
const
PaintRecord
&
paint_record
:
paint_records
)
{
update_line_metrics
(
paint_record
.
metrics
(),
paint_record
.
style
());
update_line_metrics
(
paint_record
.
metrics
(),
paint_record
.
style
(),
paint_record
.
GetPlaceholderRun
());
}
// If no fonts were actually rendered, then compute a baseline based on the
...
...
@@ -908,7 +1071,7 @@ void Paragraph::Layout(double width, bool force) {
font
.
setTypeface
(
GetDefaultSkiaTypeface
(
style
));
font
.
setSize
(
style
.
font_size
);
font
.
getMetrics
(
&
metrics
);
update_line_metrics
(
metrics
,
style
);
update_line_metrics
(
metrics
,
style
,
nullptr
);
}
// Calculate the baselines. This is only done on the first line.
...
...
@@ -1063,8 +1226,10 @@ void Paragraph::Paint(SkCanvas* canvas, double x, double y) {
paint
.
setColor
(
record
.
style
().
color
);
}
SkPoint
offset
=
base_offset
+
record
.
offset
();
PaintShadow
(
canvas
,
record
,
offset
);
canvas
->
drawTextBlob
(
record
.
text
(),
offset
.
x
(),
offset
.
y
(),
paint
);
if
(
record
.
GetPlaceholderRun
()
==
nullptr
)
{
PaintShadow
(
canvas
,
record
,
offset
);
canvas
->
drawTextBlob
(
record
.
text
(),
offset
.
x
(),
offset
.
y
(),
paint
);
}
PaintDecorations
(
canvas
,
record
,
base_offset
);
}
}
...
...
@@ -1300,6 +1465,13 @@ std::vector<Paragraph::TextBox> Paragraph::GetRectsForRange(
SkScalar
top
=
baseline
+
run
.
font_metrics
.
fAscent
;
SkScalar
bottom
=
baseline
+
run
.
font_metrics
.
fDescent
;
if
(
run
.
placeholder_run
!=
nullptr
)
{
// Use inline placeholder size as height.
top
=
baseline
-
run
.
placeholder_run
->
baseline_offset
;
bottom
=
baseline
+
run
.
placeholder_run
->
height
-
run
.
placeholder_run
->
baseline_offset
;
}
max_line
=
std
::
max
(
run
.
line_number
,
max_line
);
min_line
=
std
::
min
(
run
.
line_number
,
min_line
);
...
...
@@ -1538,6 +1710,46 @@ Paragraph::PositionWithAffinity Paragraph::GetGlyphPositionAtCoordinate(
}
}
// We don't cache this because since this returns all boxes, it is usually
// unnecessary to call this multiple times in succession.
std
::
vector
<
Paragraph
::
TextBox
>
Paragraph
::
GetRectsForPlaceholders
()
const
{
// Struct that holds calculated metrics for each line.
struct
LineBoxMetrics
{
std
::
vector
<
Paragraph
::
TextBox
>
boxes
;
// Per-line metrics for max and min coordinates for left and right boxes.
// These metrics cannot be calculated in layout generically because of
// selections that do not cover the whole line.
SkScalar
max_right
=
FLT_MIN
;
SkScalar
min_left
=
FLT_MAX
;
};
std
::
vector
<
Paragraph
::
TextBox
>
boxes
;
// Generate initial boxes and calculate metrics.
for
(
const
CodeUnitRun
&
run
:
inline_placeholder_code_unit_runs_
)
{
// Check to see if we are finished.
double
baseline
=
line_baselines_
[
run
.
line_number
];
SkScalar
top
=
baseline
+
run
.
font_metrics
.
fAscent
;
SkScalar
bottom
=
baseline
+
run
.
font_metrics
.
fDescent
;
if
(
run
.
placeholder_run
!=
nullptr
)
{
// Use inline placeholder size as height.
top
=
baseline
-
run
.
placeholder_run
->
baseline_offset
;
bottom
=
baseline
+
run
.
placeholder_run
->
height
-
run
.
placeholder_run
->
baseline_offset
;
}
// Calculate left and right.
SkScalar
left
,
right
;
left
=
run
.
x_pos
.
start
;
right
=
run
.
x_pos
.
end
;
boxes
.
emplace_back
(
SkRect
::
MakeLTRB
(
left
,
top
,
right
,
bottom
),
run
.
direction
);
}
return
boxes
;
}
Paragraph
::
Range
<
size_t
>
Paragraph
::
GetWordBoundary
(
size_t
offset
)
const
{
if
(
text_
.
size
()
==
0
)
return
Range
<
size_t
>
(
0
,
0
);
...
...
third_party/txt/src/txt/paragraph.h
浏览文件 @
a4abfb23
...
...
@@ -27,6 +27,7 @@
#include "minikin/LineBreaker.h"
#include "paint_record.h"
#include "paragraph_style.h"
#include "placeholder_run.h"
#include "styled_runs.h"
#include "third_party/googletest/googletest/include/gtest/gtest_prod.h" // nogncheck
#include "third_party/skia/include/core/SkFontMetrics.h"
...
...
@@ -39,6 +40,14 @@ namespace txt {
using
GlyphID
=
uint32_t
;
// Constant with the unicode codepoint for the "Object replacement character".
// Used as a stand-in character for Placeholder boxes.
const
int
objReplacementChar
=
0xFFFC
;
// Constant with the unicode codepoint for the "Replacement character". This is
// the character that commonly renders as a black diamond with a white question
// mark. Used to replace non-placeholder instances of 0xFFFC in the text buffer.
const
int
replacementChar
=
0xFFFD
;
// Paragraph provides Layout, metrics, and painting capabilities for text. Once
// a Paragraph is constructed with ParagraphBuilder::Build(), an example basic
// workflow can be this:
...
...
@@ -190,6 +199,17 @@ class Paragraph {
// with the top left corner as the origin, and +y direction as down.
PositionWithAffinity
GetGlyphPositionAtCoordinate
(
double
dx
,
double
dy
)
const
;
// Returns a vector of bounding boxes that bound all inline placeholders in
// the paragraph.
//
// There will be one box for each inline placeholder. The boxes will be in the
// same order as they were added to the paragraph. The bounds will always be
// tight and should fully enclose the area where the placeholder should be.
//
// More granular boxes may be obtained through GetRectsForRange, which will
// return bounds on both text as well as inline placeholders.
std
::
vector
<
Paragraph
::
TextBox
>
GetRectsForPlaceholders
()
const
;
// Finds the first and last glyphs that define a word containing the glyph at
// index offset.
Range
<
size_t
>
GetWordBoundary
(
size_t
offset
)
const
;
...
...
@@ -236,10 +256,23 @@ class Paragraph {
FRIEND_TEST
(
ParagraphTest
,
SimpleShadow
);
FRIEND_TEST
(
ParagraphTest
,
ComplexShadow
);
FRIEND_TEST
(
ParagraphTest
,
FontFallbackParagraph
);
FRIEND_TEST
(
ParagraphTest
,
InlinePlaceholder0xFFFCParagraph
);
FRIEND_TEST
(
ParagraphTest
,
FontFeaturesParagraph
);
// Starting data to layout.
std
::
vector
<
uint16_t
>
text_
;
// A vector of PlaceholderRuns, which detail the sizes, positioning and break
// behavior of the empty spaces to leave. Each placeholder span corresponds to
// a 0xFFFC (object replacement character) in text_, which indicates the
// position in the text where the placeholder will occur. There should be an
// equal number of 0xFFFC characters and elements in this vector.
std
::
vector
<
PlaceholderRun
>
inline_placeholders_
;
// The indexes of the boxes that correspond to an inline placeholder.
std
::
vector
<
size_t
>
inline_placeholder_boxes_
;
// The indexes of instances of 0xFFFC that correspond to placeholders. This is
// necessary since the user may pass in manually entered 0xFFFC values using
// AddText().
std
::
unordered_set
<
size_t
>
obj_replacement_char_indexes_
;
StyledRuns
runs_
;
ParagraphStyle
paragraph_style_
;
std
::
shared_ptr
<
FontCollection
>
font_collection_
;
...
...
@@ -304,19 +337,35 @@ class Paragraph {
bool
is_ghost
)
:
start_
(
s
),
end_
(
e
),
direction_
(
d
),
style_
(
&
st
),
is_ghost_
(
is_ghost
)
{}
// Constructs a placeholder bidi run.
BidiRun
(
size_t
s
,
size_t
e
,
TextDirection
d
,
const
TextStyle
&
st
,
PlaceholderRun
&
placeholder
)
:
start_
(
s
),
end_
(
e
),
direction_
(
d
),
style_
(
&
st
),
placeholder_run_
(
&
placeholder
)
{}
size_t
start
()
const
{
return
start_
;
}
size_t
end
()
const
{
return
end_
;
}
size_t
size
()
const
{
return
end_
-
start_
;
}
TextDirection
direction
()
const
{
return
direction_
;
}
const
TextStyle
&
style
()
const
{
return
*
style_
;
}
PlaceholderRun
*
placeholder_run
()
const
{
return
placeholder_run_
;
}
bool
is_rtl
()
const
{
return
direction_
==
TextDirection
::
rtl
;
}
// Tracks if the run represents trailing whitespace.
bool
is_ghost
()
const
{
return
is_ghost_
;
}
bool
is_placeholder_run
()
const
{
return
placeholder_run_
!=
nullptr
;
}
private:
size_t
start_
,
end_
;
TextDirection
direction_
;
const
TextStyle
*
style_
;
bool
is_ghost_
;
PlaceholderRun
*
placeholder_run_
=
nullptr
;
};
struct
GlyphPosition
{
...
...
@@ -347,13 +396,15 @@ class Paragraph {
size_t
line_number
;
SkFontMetrics
font_metrics
;
TextDirection
direction
;
const
PlaceholderRun
*
placeholder_run
;
CodeUnitRun
(
std
::
vector
<
GlyphPosition
>&&
p
,
Range
<
size_t
>
cu
,
Range
<
double
>
x
,
size_t
line
,
const
SkFontMetrics
&
metrics
,
TextDirection
dir
);
TextDirection
dir
,
const
PlaceholderRun
*
placeholder
);
void
Shift
(
double
delta
);
};
...
...
@@ -364,6 +415,8 @@ class Paragraph {
// Holds the positions of each range of code units in the text.
// Sorted in code unit index order.
std
::
vector
<
CodeUnitRun
>
code_unit_runs_
;
// Holds the positions of the inline placeholders.
std
::
vector
<
CodeUnitRun
>
inline_placeholder_code_unit_runs_
;
// The max width of the paragraph as provided in the most recent Layout()
// call.
...
...
@@ -394,6 +447,10 @@ class Paragraph {
void
SetFontCollection
(
std
::
shared_ptr
<
FontCollection
>
font_collection
);
void
SetInlinePlaceholders
(
std
::
vector
<
PlaceholderRun
>
inline_placeholders
,
std
::
unordered_set
<
size_t
>
obj_replacement_char_indexes
);
// Break the text into lines.
bool
ComputeLineBreaks
();
...
...
@@ -403,6 +460,13 @@ class Paragraph {
// Calculates and populates strut based on paragraph_style_ strut info.
void
ComputeStrut
(
StrutMetrics
*
strut
,
SkFont
&
font
);
// Adjusts the ascent and descent based on the existence and type of
// placeholder. This method sets the proper metrics to achieve the different
// PlaceholderAlignment options.
void
ComputePlaceholder
(
PlaceholderRun
*
placeholder_run
,
double
&
ascent
,
double
&
descent
);
bool
IsStrutValid
()
const
;
// Calculate the starting X offset of a line based on the line's width and
...
...
third_party/txt/src/txt/paragraph_builder.cc
浏览文件 @
a4abfb23
...
...
@@ -77,11 +77,21 @@ void ParagraphBuilder::AddText(const char* text) {
AddText
(
u16_text
);
}
void
ParagraphBuilder
::
AddPlaceholder
(
PlaceholderRun
&
span
)
{
obj_replacement_char_indexes_
.
insert
(
text_
.
size
());
runs_
.
StartRun
(
PeekStyleIndex
(),
text_
.
size
());
AddText
(
std
::
u16string
(
1ull
,
objReplacementChar
));
runs_
.
StartRun
(
PeekStyleIndex
(),
text_
.
size
());
inline_placeholders_
.
push_back
(
span
);
}
std
::
unique_ptr
<
Paragraph
>
ParagraphBuilder
::
Build
()
{
runs_
.
EndRunIfNeeded
(
text_
.
size
());
std
::
unique_ptr
<
Paragraph
>
paragraph
=
std
::
make_unique
<
Paragraph
>
();
paragraph
->
SetText
(
std
::
move
(
text_
),
std
::
move
(
runs_
));
paragraph
->
SetInlinePlaceholders
(
std
::
move
(
inline_placeholders_
),
std
::
move
(
obj_replacement_char_indexes_
));
paragraph
->
SetParagraphStyle
(
paragraph_style_
);
paragraph
->
SetFontCollection
(
font_collection_
);
SetParagraphStyle
(
paragraph_style_
);
...
...
third_party/txt/src/txt/paragraph_builder.h
浏览文件 @
a4abfb23
...
...
@@ -24,6 +24,7 @@
#include "font_collection.h"
#include "paragraph.h"
#include "paragraph_style.h"
#include "placeholder_run.h"
#include "styled_runs.h"
#include "text_style.h"
...
...
@@ -66,6 +67,14 @@ class ParagraphBuilder {
// Converts to u16string before adding.
void
AddText
(
const
char
*
text
);
// Pushes the information requried to leave an open space, where Flutter may
// draw a custom placeholder into.
//
// Internally, this method adds a single object replacement character (0xFFFC)
// and emplaces a new PlaceholderRun instance to the vector of inline
// placeholders.
void
AddPlaceholder
(
PlaceholderRun
&
span
);
void
SetParagraphStyle
(
const
ParagraphStyle
&
style
);
// Constructs a Paragraph object that can be used to layout and paint the text
...
...
@@ -74,6 +83,15 @@ class ParagraphBuilder {
private:
std
::
vector
<
uint16_t
>
text_
;
// A vector of PlaceholderRuns, which detail the sizes, positioning and break
// behavior of the empty spaces to leave. Each placeholder span corresponds to
// a 0xFFFC (object replacement character) in text_, which indicates the
// position in the text where the placeholder will occur. There should be an
// equal number of 0xFFFC characters and elements in this vector.
std
::
vector
<
PlaceholderRun
>
inline_placeholders_
;
// The indexes of the obj replacement characters added through
// ParagraphBuilder::addPlaceholder().
std
::
unordered_set
<
size_t
>
obj_replacement_char_indexes_
;
std
::
vector
<
size_t
>
style_stack_
;
std
::
shared_ptr
<
FontCollection
>
font_collection_
;
StyledRuns
runs_
;
...
...
third_party/txt/src/txt/placeholder_run.cc
0 → 100644
浏览文件 @
a4abfb23
/*
* Copyright 2019 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "placeholder_run.h"
namespace
txt
{
PlaceholderRun
::
PlaceholderRun
()
{}
PlaceholderRun
::
PlaceholderRun
(
double
width
,
double
height
,
PlaceholderAlignment
alignment
,
TextBaseline
baseline
,
double
baseline_offset
)
:
width
(
width
),
height
(
height
),
alignment
(
alignment
),
baseline
(
baseline
),
baseline_offset
(
baseline_offset
)
{}
}
// namespace txt
third_party/txt/src/txt/placeholder_run.h
0 → 100644
浏览文件 @
a4abfb23
/*
* Copyright 2019 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LIB_TXT_SRC_PLACEHOLDER_RUN_H_
#define LIB_TXT_SRC_PLACEHOLDER_RUN_H_
#include "text_baseline.h"
namespace
txt
{
/// Where to vertically align the placeholder relative to the surrounding text.
enum
class
PlaceholderAlignment
{
/// Match the baseline of the placeholder with the baseline.
kBaseline
,
/// Align the bottom edge of the placeholder with the baseline such that the
/// placeholder sits on top of the baseline.
kAboveBaseline
,
/// Align the top edge of the placeholder with the baseline specified in
/// such that the placeholder hangs below the baseline.
kBelowBaseline
,
/// Align the top edge of the placeholder with the top edge of the font.
/// When the placeholder is very tall, the extra space will hang from
/// the top and extend through the bottom of the line.
kTop
,
/// Align the bottom edge of the placeholder with the top edge of the font.
/// When the placeholder is very tall, the extra space will rise from
/// the bottom and extend through the top of the line.
kBottom
,
/// Align the middle of the placeholder with the middle of the text. When the
/// placeholder is very tall, the extra space will grow equally from
/// the top and bottom of the line.
kMiddle
,
};
// Represents the metrics required to fully define a rect that will fit a
// placeholder.
//
// LibTxt will leave an empty space in the layout of the text of the size
// defined by this class. After layout, the framework will draw placeholders
// into the reserved space.
class
PlaceholderRun
{
public:
double
width
=
0
;
double
height
=
0
;
PlaceholderAlignment
alignment
;
TextBaseline
baseline
;
// Distance from the top edge of the rect to the baseline position. This
// baseline will be aligned against the alphabetic baseline of the surrounding
// text.
//
// Positive values drop the baseline lower (positions the rect higher) and
// small or negative values will cause the rect to be positioned underneath
// the line. When baseline == height, the bottom edge of the rect will rest on
// the alphabetic baseline.
double
baseline_offset
=
0
;
PlaceholderRun
();
PlaceholderRun
(
double
width
,
double
height
,
PlaceholderAlignment
alignment
,
TextBaseline
baseline
,
double
baseline_offset
);
};
}
// namespace txt
#endif // LIB_TXT_SRC_PLACEHOLDER_RUN_H_
third_party/txt/tests/paragraph_unittests.cc
浏览文件 @
a4abfb23
此差异已折叠。
点击以展开。
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录