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

Commit 9aa23af

Browse files
author
Yuncong Zhang
committed
Compute total number of LineStyleRuns in advance.
1 parent 0ee21d6 commit 9aa23af

File tree

2 files changed

+73
-25
lines changed

2 files changed

+73
-25
lines changed

Runtime/ui/txt/linebreaker.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,14 @@ class LineBreaker {
7777
const float ScoreInfty = float.MaxValue;
7878
const float ScoreDesperate = 1e10f;
7979

80+
int _lineLimit = 0;
81+
82+
// Limit number of lines, 0 means no limit
83+
public int lineLimit {
84+
get { return this._lineLimit; }
85+
set { this._lineLimit = value; }
86+
}
87+
8088
public static LineBreaker instance {
8189
get {
8290
if(_instance == null)
@@ -291,8 +299,10 @@ void _pushGreedyBreak() {
291299
}
292300

293301
void _pushBreak(int offset, float width) {
294-
this._breaks.Add(offset);
295-
this._widths.Add(width);
302+
if (this.lineLimit == 0 || this._breaks.Count < this.lineLimit) {
303+
this._breaks.Add(offset);
304+
this._widths.Add(width);
305+
}
296306
}
297307
}
298308
}

Runtime/ui/txt/paragraph.cs

Lines changed: 61 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,10 @@ public LineRange(int start, int end, int endExcludingWhitespace, int endIncludin
197197
float[] _lineHeights;
198198
GlyphPosition[] glyphPositions;
199199
int _lineCount;
200-
List<PaintRecord> _paintRecords = new List<PaintRecord>();
201-
List<CodeUnitRun> _codeUnitRuns = new List<CodeUnitRun>();
200+
PaintRecord[] _paintRecords;
201+
CodeUnitRun[] _codeUnitRuns;
202+
int _paintRecordsCount;
203+
int _codeUnitRunsCount;
202204
bool _didExceedMaxLines;
203205
TabStops _tabStops = new TabStops();
204206

@@ -248,11 +250,13 @@ public bool didExceedMaxLines {
248250
}
249251

250252
public void paint(Canvas canvas, Offset offset) {
251-
foreach (var paintRecord in this._paintRecords) {
253+
for (int i = 0; i < this._paintRecordsCount; i++) {
254+
var paintRecord = this._paintRecords[i];
252255
this.paintBackground(canvas, paintRecord, offset);
253256
}
254257

255-
foreach (var paintRecord in this._paintRecords) {
258+
for (int i = 0; i < this._paintRecordsCount; i++) {
259+
var paintRecord = this._paintRecords[i];
256260
var paint = new Paint {
257261
filterMode = FilterMode.Bilinear,
258262
color = paintRecord.style.color
@@ -276,10 +280,9 @@ public void layout(ParagraphConstraints constraints) {
276280

277281
this._needsLayout = false;
278282
this._width = Mathf.Floor(constraints.width);
279-
this._paintRecords.Clear();
280-
this._codeUnitRuns.Clear();
281283

282-
this._computeLineBreak();
284+
int lineStyleRunsCount = this._computeLineBreak();
285+
283286
if (this._glyphLines == null || this._glyphLines.Length < this._lineRanges.Count) {
284287
this._glyphLines = new GlyphLine[this._lineRanges.Count];
285288
}
@@ -292,6 +295,18 @@ public void layout(ParagraphConstraints constraints) {
292295
this._lineHeights = new float[this._lineRanges.Count];
293296
}
294297

298+
if (this._paintRecords == null || this._paintRecords.Length < lineStyleRunsCount) {
299+
this._paintRecords = new PaintRecord[lineStyleRunsCount];
300+
}
301+
302+
this._paintRecordsCount = 0;
303+
304+
if (this._codeUnitRuns == null || this._codeUnitRuns.Length < lineStyleRunsCount) {
305+
this._codeUnitRuns = new CodeUnitRun[lineStyleRunsCount];
306+
}
307+
308+
this._codeUnitRunsCount = 0;
309+
295310
int styleMaxLines = this._paragraphStyle.maxLines ?? int.MaxValue;
296311
this._didExceedMaxLines = this._lineRanges.Count > styleMaxLines;
297312

@@ -461,15 +476,16 @@ public void layout(ParagraphConstraints constraints) {
461476
var metrics = FontMetrics.fromFont(font, style.UnityFontSize);
462477
PaintRecord paintRecord = new PaintRecord(style, runXOffset, 0, builder.make(),
463478
metrics, advance);
464-
this._paintRecords.Add(paintRecord);
479+
this._paintRecords[this._paintRecordsCount++] = paintRecord;
465480
runXOffset += advance;
466481

467482
// Create code unit run
468-
this._codeUnitRuns.Add(new CodeUnitRun(
483+
CodeUnitRun codeUnitRun = new CodeUnitRun(
469484
this.glyphPositions,
470485
new Range<int>(start, end),
471486
new Range<float>(this.glyphPositions[0].xPos.start, this.glyphPositions.last().xPos.end),
472-
lineNumber, TextDirection.ltr, glyphPositionStyleRunStart, textCount));
487+
lineNumber, TextDirection.ltr, glyphPositionStyleRunStart, textCount);
488+
this._codeUnitRuns[this._codeUnitRunsCount++] = codeUnitRun;
473489

474490
lineStyleRunIndex++;
475491
}
@@ -504,7 +520,7 @@ void updateLineMetrics(FontMetrics metrics, float styleHeight) {
504520

505521
if (lineStyleRunCount != 0) {
506522
for (int i = 0; i < lineStyleRunCount; i++) {
507-
var paintRecord = this._paintRecords[this._paintRecords.Count - i - 1];
523+
var paintRecord = this._paintRecords[this._paintRecordsCount - i - 1];
508524
updateLineMetrics(paintRecord.metrics, paintRecord.style.height);
509525
}
510526
}
@@ -538,9 +554,9 @@ void updateLineMetrics(FontMetrics metrics, float styleHeight) {
538554
this._glyphLines[lineNumber] =
539555
new GlyphLine(this.glyphPositions, glyphPositionLineStart, count, nextLineStart - lineStart);
540556
for (int i = 0; i < lineStyleRunCount; i++) {
541-
var paintRecord = this._paintRecords[this._paintRecords.Count - 1 - i];
557+
var paintRecord = this._paintRecords[this._paintRecordsCount - 1 - i];
542558
paintRecord.shift(lineXOffset, yOffset);
543-
this._paintRecords[this._paintRecords.Count - 1 - i] = paintRecord;
559+
this._paintRecords[this._paintRecordsCount - 1 - i] = paintRecord;
544560
}
545561
}
546562

@@ -782,33 +798,48 @@ public int getLineCount() {
782798
return this._lineCount;
783799
}
784800

785-
void _computeLineBreak() {
801+
int _computeLineBreak() {
786802
this._lineRanges.Clear();
787803
this._lineWidths.Clear();
788804
this._maxIntrinsicWidth = 0;
789805

806+
int lineLimit = this._paragraphStyle.ellipsized()
807+
? this._paragraphStyle.maxLines ?? 1
808+
: this._paragraphStyle.maxLines ?? 0;
809+
790810
var newLinePositions = LineBreaker.newLinePositions;
791811
this._computeNewLinePositions(newLinePositions);
792812

793813
var lineBreaker = LineBreaker.instance;
794814
int runIndex = 0;
815+
int countRuns = 0;
795816
for (var newlineIndex = 0; newlineIndex < newLinePositions.Count; ++newlineIndex) {
817+
if (lineLimit != 0 && this._lineRanges.Count >= lineLimit) {
818+
break;
819+
}
796820
var blockStart = newlineIndex > 0 ? newLinePositions[newlineIndex - 1] + 1 : 0;
797821
var blockEnd = newLinePositions[newlineIndex];
798822
var blockSize = blockEnd - blockStart;
799823
if (blockSize == 0) {
800824
this._addEmptyLine(blockStart, blockEnd);
801825
continue;
802826
}
827+
if (lineLimit != 0 && this._lineRanges.Count >= lineLimit) {
828+
break;
829+
}
803830

804-
this._resetLineBreaker(lineBreaker, blockStart, blockSize);
805-
runIndex = this._addStyleRuns(lineBreaker, runIndex, blockStart, blockEnd);
831+
this._resetLineBreaker(lineBreaker, blockStart, blockSize,
832+
lineLimit == 0 ? 0 : lineLimit - this._lineRanges.Count);
833+
countRuns += this._addStyleRuns(lineBreaker, ref runIndex, blockStart, blockEnd);
806834

807835
int breaksCount = lineBreaker.computeBreaks();
808-
this._updateBreaks(lineBreaker, breaksCount, blockStart);
836+
countRuns += breaksCount - 1;
837+
this._updateBreaks(lineBreaker, breaksCount, blockStart, blockEnd);
809838

810839
lineBreaker.finish();
811840
}
841+
842+
return countRuns;
812843
}
813844

814845
void _addEmptyLine(int blockStart, int blockEnd) {
@@ -817,28 +848,35 @@ void _addEmptyLine(int blockStart, int blockEnd) {
817848
this._lineWidths.Add(0);
818849
}
819850

820-
void _resetLineBreaker(LineBreaker lineBreaker, int blockStart, int blockSize) {
851+
void _resetLineBreaker(LineBreaker lineBreaker, int blockStart, int blockSize, int lineLimit) {
821852
lineBreaker.setLineWidth(this._width);
822853
lineBreaker.resize(blockSize);
823854
lineBreaker.setTabStops(this._tabStops);
824855
lineBreaker.setText(this._text, blockStart, blockSize);
856+
lineBreaker.lineLimit = lineLimit;
825857
}
826858

827-
int _addStyleRuns(LineBreaker lineBreaker, int runIndex, int blockStart, int blockEnd) {
859+
int _addStyleRuns(LineBreaker lineBreaker, ref int runIndex, int blockStart, int blockEnd) {
860+
int countRuns = 0;
828861
while (runIndex < this._runs.size) {
829862
var run = this._runs.getRun(runIndex);
830863
if (run.start >= blockEnd) {
831864
break;
832865
}
833866

834-
if (run.end < blockStart) {
867+
if (lineBreaker.lineLimit != 0 && lineBreaker.getBreaks().Count >= lineBreaker.lineLimit) {
868+
break;
869+
}
870+
871+
if (run.end <= blockStart) {
835872
runIndex++;
836873
continue;
837874
}
838875

839876
int runStart = Mathf.Max(run.start, blockStart) - blockStart;
840877
int runEnd = Mathf.Min(run.end, blockEnd) - blockStart;
841878
lineBreaker.addStyleRun(run.style, runStart, runEnd);
879+
countRuns++;
842880

843881
if (run.end > blockEnd) {
844882
break;
@@ -847,17 +885,17 @@ int _addStyleRuns(LineBreaker lineBreaker, int runIndex, int blockStart, int blo
847885
runIndex++;
848886
}
849887

850-
return runIndex;
888+
return countRuns;
851889
}
852890

853-
void _updateBreaks(LineBreaker lineBreaker, int breaksCount, int blockStart) {
891+
void _updateBreaks(LineBreaker lineBreaker, int breaksCount, int blockStart, int blockEnd) {
854892
List<int> breaks = lineBreaker.getBreaks();
855893
List<float> widths = lineBreaker.getWidths();
856894
for (int i = 0; i < breaksCount; ++i) {
857895
var breakStart = i > 0 ? breaks[i - 1] : 0;
858896
var lineStart = breakStart + blockStart;
859897
var lineEnd = breaks[i] + blockStart;
860-
bool hardBreak = i == breaksCount - 1;
898+
bool hardBreak = lineEnd == blockEnd;
861899
var lineEndIncludingNewline =
862900
hardBreak && lineEnd < this._text.Length ? lineEnd + 1 : lineEnd;
863901
var lineEndExcludingWhitespace = lineEnd;

0 commit comments

Comments
 (0)