Skip to content
This repository was archived by the owner on Apr 29, 2021. It is now read-only.

Commit 5b11e30

Browse files
committed
text painter
1 parent 6bbf08b commit 5b11e30

File tree

1 file changed

+61
-21
lines changed

1 file changed

+61
-21
lines changed

Runtime/painting/text_painter.cs

Lines changed: 61 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
using System;
2-
using System.Collections.Generic;
1+
using System.Collections.Generic;
32
using Unity.UIWidgets.foundation;
43
using Unity.UIWidgets.service;
54
using Unity.UIWidgets.ui;
@@ -66,7 +65,7 @@ public string ellipsis {
6665
public TextSpan text {
6766
get { return this._text; }
6867
set {
69-
if ((this._text == null && value == null) || (this._text != null && this.text.Equals(value))) {
68+
if ((this._text == null && value == null) || (this._text != null && this.text.Equals(value))) {
7069
return;
7170
}
7271

@@ -353,41 +352,82 @@ float _applyFloatingPointHack(float layoutValue) {
353352
return Mathf.Ceil(layoutValue);
354353
}
355354

355+
const int _zwjUtf16 = 0x200d;
356356

357357
Offset _getOffsetFromUpstream(int offset, Rect caretPrototype) {
358-
var prevCodeUnit = this._text.codeUnitAt(offset - 1);
358+
string flattenedText = this._text.toPlainText();
359+
var prevCodeUnit = this._text.codeUnitAt(Mathf.Max(0, offset - 1));
359360
if (prevCodeUnit == null) {
360361
return null;
361362
}
362363

363-
var prevRuneOffset = _isUtf16Surrogate((int) prevCodeUnit) ? offset - 2 : offset - 1;
364-
var boxes = this._paragraph.getRectsForRange(prevRuneOffset, offset);
365-
if (boxes.Count == 0) {
366-
return null;
364+
bool needsSearch = _isUtf16Surrogate(prevCodeUnit.Value) || this._text.codeUnitAt(offset) == _zwjUtf16;
365+
int graphemeClusterLength = needsSearch ? 2 : 1;
366+
List<TextBox> boxes = null;
367+
while ((boxes == null || boxes.isEmpty()) && flattenedText != null) {
368+
int prevRuneOffset = offset - graphemeClusterLength;
369+
boxes = this._paragraph.getRectsForRange(prevRuneOffset, offset);
370+
if (boxes.isEmpty()) {
371+
if (!needsSearch) {
372+
break;
373+
}
374+
375+
if (prevRuneOffset < -flattenedText.Length) {
376+
break;
377+
}
378+
379+
graphemeClusterLength *= 2;
380+
continue;
381+
}
382+
383+
TextBox box = boxes[0];
384+
const int NEWLINE_CODE_UNIT = 10;
385+
if (prevCodeUnit == NEWLINE_CODE_UNIT) {
386+
return new Offset(this._emptyOffset.dx, box.bottom);
387+
}
388+
389+
float caretEnd = box.end;
390+
float dx = box.direction == TextDirection.rtl ? caretEnd - caretPrototype.width : caretEnd;
391+
return new Offset(dx, box.top);
367392
}
368393

369-
var box = boxes[0];
370-
var caretEnd = box.end;
371-
var dx = box.direction == TextDirection.rtl ? caretEnd : caretEnd - caretPrototype.width;
372-
return new Offset(dx, box.top);
394+
return null;
373395
}
374396

375397
Offset _getOffsetFromDownstream(int offset, Rect caretPrototype) {
376-
var nextCodeUnit = this._text.codeUnitAt(offset - 1);
398+
string flattenedText = this._text.toPlainText();
399+
var nextCodeUnit =
400+
this._text.codeUnitAt(Mathf.Min(offset, flattenedText == null ? 0 : flattenedText.Length - 1));
377401
if (nextCodeUnit == null) {
378402
return null;
379403
}
380404

381-
var nextRuneOffset = _isUtf16Surrogate((int) nextCodeUnit) ? offset + 2 : offset + 1;
382-
var boxes = this._paragraph.getRectsForRange(offset, nextRuneOffset);
383-
if (boxes.Count == 0) {
384-
return null;
405+
bool needsSearch = _isUtf16Surrogate(nextCodeUnit.Value) || nextCodeUnit == _zwjUtf16;
406+
int graphemeClusterLength = needsSearch ? 2 : 1;
407+
List<TextBox> boxes = null;
408+
while ((boxes == null || boxes.isEmpty()) && flattenedText != null) {
409+
int nextRuneOffset = offset + graphemeClusterLength;
410+
boxes = this._paragraph.getRectsForRange(offset, nextRuneOffset);
411+
if (boxes.isEmpty()) {
412+
if (!needsSearch) {
413+
break;
414+
}
415+
416+
if (nextRuneOffset >= flattenedText.Length << 1) {
417+
break;
418+
}
419+
420+
graphemeClusterLength *= 2;
421+
continue;
422+
}
423+
424+
TextBox box = boxes[boxes.Count - 1];
425+
float caretStart = box.start;
426+
float dx = box.direction == TextDirection.rtl ? caretStart - caretPrototype.width : caretStart;
427+
return new Offset(dx, box.top);
385428
}
386429

387-
var box = boxes[0];
388-
var caretStart = box.start;
389-
var dx = box.direction == TextDirection.rtl ? caretStart - caretPrototype.width : caretStart;
390-
return new Offset(dx, box.top);
430+
return null;
391431
}
392432

393433
Offset _emptyOffset {

0 commit comments

Comments
 (0)