Unverified Commit 90b8a549 authored by Harry Terkelsen's avatar Harry Terkelsen Committed by GitHub

Only stop search for upstream character if we hit a newline (#86960)

parent 184e5871
......@@ -690,6 +690,9 @@ class TextPainter {
if (prevCodeUnit == null)
return null;
// If the upstream character is a newline, cursor is at start of next line
const int NEWLINE_CODE_UNIT = 10;
// Check for multi-code-unit glyphs such as emojis or zero width joiner.
final bool needsSearch = _isUtf16Surrogate(prevCodeUnit) || _text!.codeUnitAt(offset) == _zwjUtf16 || _isUnicodeDirectionality(prevCodeUnit);
int graphemeClusterLength = needsSearch ? 2 : 1;
......@@ -703,7 +706,7 @@ class TextPainter {
if (boxes.isEmpty) {
// When we are at the beginning of the line, a non-surrogate position will
// return empty boxes. We break and try from downstream instead.
if (!needsSearch) {
if (!needsSearch && prevCodeUnit == NEWLINE_CODE_UNIT) {
break; // Only perform one iteration if no search is required.
}
if (prevRuneOffset < -flattenedText.length) {
......@@ -718,8 +721,6 @@ class TextPainter {
}
final TextBox box = boxes.first;
// If the upstream character is a newline, cursor is at start of next line
const int NEWLINE_CODE_UNIT = 10;
if (prevCodeUnit == NEWLINE_CODE_UNIT) {
return Rect.fromLTRB(_emptyOffset.dx, box.bottom, _emptyOffset.dx, box.bottom + box.bottom - box.top);
}
......
......@@ -8,6 +8,9 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
const bool isCanvasKit =
bool.fromEnvironment('FLUTTER_WEB_USE_SKIA', defaultValue: false);
void main() {
test('TextPainter caret test', () {
final TextPainter painter = TextPainter()
......@@ -123,7 +126,7 @@ void main() {
expect(caretOffset.dx, 98); // <medium skin tone modifier>
caretOffset = painter.getOffsetForCaret(const ui.TextPosition(offset: 23), ui.Rect.zero);
expect(caretOffset.dx, 126); // end of string
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/56308
}, skip: isBrowser && !isCanvasKit); // https://github.com/flutter/flutter/issues/56308
test('TextPainter caret center space test', () {
final TextPainter painter = TextPainter()
......@@ -145,7 +148,7 @@ void main() {
expect(caretOffset.dx, 35);
caretOffset = painter.getOffsetForCaret(const ui.TextPosition(offset: 2), ui.Rect.zero);
expect(caretOffset.dx, 49);
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/56308
}, skip: isBrowser && !isCanvasKit); // https://github.com/flutter/flutter/issues/56308
test('TextPainter error test', () {
final TextPainter painter = TextPainter(textDirection: TextDirection.ltr);
......@@ -743,7 +746,7 @@ void main() {
expect(painter.inlinePlaceholderBoxes![11], const TextBox.fromLTRBD(250, 30, 300, 60, TextDirection.ltr));
expect(painter.inlinePlaceholderBoxes![12], const TextBox.fromLTRBD(300, 30, 351, 60, TextDirection.ltr));
expect(painter.inlinePlaceholderBoxes![13], const TextBox.fromLTRBD(351, 30, 401, 60, TextDirection.ltr));
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/42086
}, skip: isBrowser && !isCanvasKit); // https://github.com/flutter/flutter/issues/42086
// Null values are valid. See https://github.com/flutter/flutter/pull/48346#issuecomment-584839221
test('TextPainter set TextHeightBehavior null test', () {
......@@ -832,7 +835,7 @@ void main() {
ui.Rect.zero,
)!;
expect(caretHeight, 50.0);
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/56308
}, skip: isBrowser && !isCanvasKit); // https://github.com/flutter/flutter/issues/56308
group('TextPainter line-height', () {
test('half-leading', () {
......@@ -952,7 +955,7 @@ void main() {
).first.toRect();
expect(glyphBox, newGlyphBox);
});
}, skip: isBrowser);
}, skip: isBrowser && !isCanvasKit);
test('TextPainter handles invalid UTF-16', () {
Object? exception;
......@@ -971,6 +974,22 @@ void main() {
expect(painter.width, equals(fontSize));
expect(exception, isNotNull);
}, skip: kIsWeb);
test('Diacritic', () {
final TextPainter painter = TextPainter()
..textDirection = TextDirection.ltr;
// Two letters followed by a diacritic
const String text = 'ฟห้';
painter.text = const TextSpan(text: text);
painter.layout();
final ui.Offset caretOffset = painter.getOffsetForCaret(
const ui.TextPosition(
offset: text.length, affinity: TextAffinity.upstream),
ui.Rect.zero);
expect(caretOffset.dx, painter.width);
}, skip: kIsWeb && !isCanvasKit);
}
class MockCanvas extends Fake implements Canvas {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment