Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
a282058d
Unverified
Commit
a282058d
authored
Dec 19, 2018
by
Gary Qian
Committed by
GitHub
Dec 19, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Use full textspan tree instead of top level textspan (#25574)
parent
b17feefc
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
34 additions
and
7 deletions
+34
-7
text_painter.dart
packages/flutter/lib/src/painting/text_painter.dart
+9
-7
text_painter_test.dart
packages/flutter/test/painting/text_painter_test.dart
+25
-0
No files found.
packages/flutter/lib/src/painting/text_painter.dart
View file @
a282058d
...
...
@@ -420,6 +420,7 @@ class TextPainter {
// TODO(garyq): Use actual extended grapheme cluster length instead of
// an increasing cluster length amount to achieve deterministic performance.
Offset
_getOffsetFromUpstream
(
int
offset
,
Rect
caretPrototype
)
{
final
String
flattenedText
=
_text
.
toPlainText
();
final
int
prevCodeUnit
=
_text
.
codeUnitAt
(
max
(
0
,
offset
-
1
));
if
(
prevCodeUnit
==
null
)
return
null
;
...
...
@@ -427,7 +428,7 @@ class TextPainter {
final
bool
needsSearch
=
_isUtf16Surrogate
(
prevCodeUnit
)
||
_text
.
codeUnitAt
(
offset
)
==
_zwjUtf16
;
int
graphemeClusterLength
=
needsSearch
?
2
:
1
;
List
<
TextBox
>
boxes
=
<
TextBox
>[];
while
(
boxes
.
isEmpty
&&
_text
.
t
ext
!=
null
)
{
while
(
boxes
.
isEmpty
&&
flattenedT
ext
!=
null
)
{
final
int
prevRuneOffset
=
offset
-
graphemeClusterLength
;
boxes
=
_paragraph
.
getBoxesForRange
(
prevRuneOffset
,
offset
);
// When the range does not include a full cluster, no boxes will be returned.
...
...
@@ -436,7 +437,7 @@ class TextPainter {
// return empty boxes. We break and try from downstream instead.
if
(!
needsSearch
)
break
;
// Only perform one iteration if no search is required.
if
(
prevRuneOffset
<
-
_text
.
t
ext
.
length
)
if
(
prevRuneOffset
<
-
flattenedT
ext
.
length
)
break
;
// Stop iterating when beyond the max length of the text.
// Multiply by two to log(n) time cover the entire text span. This allows
// faster discovery of very long clusters and reduces the possibility
...
...
@@ -445,7 +446,7 @@ class TextPainter {
graphemeClusterLength
*=
2
;
continue
;
}
final
TextBox
box
=
boxes
[
0
]
;
final
TextBox
box
=
boxes
.
first
;
final
double
caretEnd
=
box
.
end
;
final
double
dx
=
box
.
direction
==
TextDirection
.
rtl
?
caretEnd
-
caretPrototype
.
width
:
caretEnd
;
return
Offset
(
dx
,
box
.
top
);
...
...
@@ -456,15 +457,16 @@ class TextPainter {
// TODO(garyq): Use actual extended grapheme cluster length instead of
// an increasing cluster length amount to achieve deterministic performance.
Offset
_getOffsetFromDownstream
(
int
offset
,
Rect
caretPrototype
)
{
final
String
flattenedText
=
_text
.
toPlainText
();
// We cap the offset at the final index of the _text.
final
int
nextCodeUnit
=
_text
.
codeUnitAt
(
min
(
offset
,
_text
.
text
==
null
?
0
:
_text
.
t
ext
.
length
-
1
));
final
int
nextCodeUnit
=
_text
.
codeUnitAt
(
min
(
offset
,
flattenedText
==
null
?
0
:
flattenedT
ext
.
length
-
1
));
if
(
nextCodeUnit
==
null
)
return
null
;
// Check for multi-code-unit glyphs such as emojis or zero width joiner
final
bool
needsSearch
=
_isUtf16Surrogate
(
nextCodeUnit
)
||
nextCodeUnit
==
_zwjUtf16
;
int
graphemeClusterLength
=
needsSearch
?
2
:
1
;
List
<
TextBox
>
boxes
=
<
TextBox
>[];
while
(
boxes
.
isEmpty
&&
_text
.
t
ext
!=
null
)
{
while
(
boxes
.
isEmpty
&&
flattenedT
ext
!=
null
)
{
final
int
nextRuneOffset
=
offset
+
graphemeClusterLength
;
boxes
=
_paragraph
.
getBoxesForRange
(
offset
,
nextRuneOffset
);
// When the range does not include a full cluster, no boxes will be returned.
...
...
@@ -473,7 +475,7 @@ class TextPainter {
// return empty boxes. We break and try from upstream instead.
if
(!
needsSearch
)
break
;
// Only perform one iteration if no search is required.
if
(
nextRuneOffset
>=
_text
.
t
ext
.
length
<<
1
)
if
(
nextRuneOffset
>=
flattenedT
ext
.
length
<<
1
)
break
;
// Stop iterating when beyond the max length of the text.
// Multiply by two to log(n) time cover the entire text span. This allows
// faster discovery of very long clusters and reduces the possibility
...
...
@@ -482,7 +484,7 @@ class TextPainter {
graphemeClusterLength
*=
2
;
continue
;
}
final
TextBox
box
=
boxes
[
0
]
;
final
TextBox
box
=
boxes
.
last
;
final
double
caretStart
=
box
.
start
;
final
double
dx
=
box
.
direction
==
TextDirection
.
rtl
?
caretStart
-
caretPrototype
.
width
:
caretStart
;
return
Offset
(
dx
,
box
.
top
);
...
...
packages/flutter/test/painting/text_painter_test.dart
View file @
a282058d
...
...
@@ -29,6 +29,31 @@ void main() {
expect
(
caretOffset
.
dx
,
painter
.
width
);
});
test
(
'TextPainter null text test'
,
()
{
final
TextPainter
painter
=
TextPainter
()
..
textDirection
=
TextDirection
.
ltr
;
List
<
TextSpan
>
children
=
<
TextSpan
>[
const
TextSpan
(
text:
'B'
),
const
TextSpan
(
text:
'C'
)];
painter
.
text
=
TextSpan
(
text:
null
,
children:
children
);
painter
.
layout
();
Offset
caretOffset
=
painter
.
getOffsetForCaret
(
const
ui
.
TextPosition
(
offset:
0
),
ui
.
Rect
.
zero
);
expect
(
caretOffset
.
dx
,
0
);
caretOffset
=
painter
.
getOffsetForCaret
(
const
ui
.
TextPosition
(
offset:
1
),
ui
.
Rect
.
zero
);
expect
(
caretOffset
.
dx
,
painter
.
width
/
2
);
caretOffset
=
painter
.
getOffsetForCaret
(
const
ui
.
TextPosition
(
offset:
2
),
ui
.
Rect
.
zero
);
expect
(
caretOffset
.
dx
,
painter
.
width
);
children
=
<
TextSpan
>[];
painter
.
text
=
TextSpan
(
text:
null
,
children:
children
);
painter
.
layout
();
caretOffset
=
painter
.
getOffsetForCaret
(
const
ui
.
TextPosition
(
offset:
0
),
ui
.
Rect
.
zero
);
expect
(
caretOffset
.
dx
,
0
);
caretOffset
=
painter
.
getOffsetForCaret
(
const
ui
.
TextPosition
(
offset:
1
),
ui
.
Rect
.
zero
);
expect
(
caretOffset
.
dx
,
0
);
});
test
(
'TextPainter caret emoji test'
,
()
{
final
TextPainter
painter
=
TextPainter
()
..
textDirection
=
TextDirection
.
ltr
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment