|
|
|
|
|
|
using System; |
|
|
|
using System.Collections; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.Linq; |
|
|
|
using Unity.UIWidgets.foundation; |
|
|
|
using UnityEngine; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ParagraphStyle _paragraphStyle; |
|
|
|
List<LineRange> _lineRanges = new List<LineRange>(); |
|
|
|
|
|
|
|
|
|
|
|
// float[] _lineBaseLines;
|
|
|
|
GlyphLine[] _glyphLines; |
|
|
|
GlyphPosition[] _glyphPositions; |
|
|
|
|
|
|
public bool didExceedMaxLines { |
|
|
|
get { return this._didExceedMaxLines; } |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static List<Paragraph> _paragraphs = new List<Paragraph>(); |
|
|
|
|
|
|
|
public static Paragraph create() { |
|
|
|
|
|
|
|
|
|
|
Paragraph ret = _paragraphs.last(); |
|
|
|
_paragraphs.RemoveAt(_paragraphs.Count-1); |
|
|
|
_paragraphs.RemoveAt(_paragraphs.Count - 1); |
|
|
|
return ret; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
this._width = Mathf.Floor(constraints.width); |
|
|
|
|
|
|
|
int lineStyleRunsCount = this._computeLineBreak(); |
|
|
|
|
|
|
|
|
|
|
|
if (this._glyphLines == null || this._glyphLines.Length < this._lineRangeCount) { |
|
|
|
this._glyphLines = new GlyphLine[LayoutUtils.minPowerOfTwo(this._lineRangeCount)]; |
|
|
|
} |
|
|
|
|
|
|
if (this._paintRecords == null || this._paintRecords.Length < lineStyleRunsCount) { |
|
|
|
this._paintRecords = new PaintRecord[LayoutUtils.minPowerOfTwo(lineStyleRunsCount)]; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
this._paintRecordsCount = 0; |
|
|
|
|
|
|
|
if (this._codeUnitRuns == null || this._codeUnitRuns.Length < lineStyleRunsCount) { |
|
|
|
|
|
|
|
|
|
|
TextBlobBuilder builder = new TextBlobBuilder(); |
|
|
|
int ellipsizedLength = this._text.Length + (this._paragraphStyle.ellipsis?.Length ?? 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
builder.setPositions(this._textBlobPositions); |
|
|
|
// this._glyphLines and this._codeUnitRuns will refer to this array for glyph positions
|
|
|
|
if (this._glyphPositions == null || this._glyphPositions.Length < ellipsizedLength) { |
|
|
|
|
|
|
// Pointer to the _glyphPositions array, to keep track of where the next glyph is stored
|
|
|
|
int pGlyphPositions = 0; |
|
|
|
|
|
|
|
|
|
|
|
// Compute max(NumberOfWords(line) for line in lines), to determine the size of word buffers
|
|
|
|
int maxWordCount = this._computeMaxWordCount(); |
|
|
|
|
|
|
|
|
|
|
(lineNumber == lineLimit - 1 || this._paragraphStyle.maxLines == null)) { |
|
|
|
maxTextCount += ellipsis.Length; |
|
|
|
} |
|
|
|
|
|
|
|
// Allocate the advances and positions to store the layout result
|
|
|
|
// TODO: find a way to compute the maxTextCount for the entire paragraph, so that this allocation
|
|
|
|
// happens only once
|
|
|
|
|
|
|
int truncateCount = Layout.computeTruncateCount(runXOffset, text, textStart, |
|
|
|
textCount, style, this._width - ellipsisWidth, this._tabStops); |
|
|
|
|
|
|
|
if(!(this._ellipsizedLength == textStart + textCount - truncateCount && |
|
|
|
this._ellipsizedText.Length == this._ellipsizedLength + ellipsis.Length && |
|
|
|
this._ellipsizedText.EndsWith(ellipsis))) { |
|
|
|
if (!(this._ellipsizedLength == textStart + textCount - truncateCount && |
|
|
|
this._ellipsizedText.Length == this._ellipsizedLength + ellipsis.Length && |
|
|
|
this._ellipsizedText.EndsWith(ellipsis))) { |
|
|
|
|
|
|
|
text = this._ellipsizedText; |
|
|
|
textCount = text.Length - textStart; |
|
|
|
D.assert(textCount != 0); |
|
|
|
|
|
|
this._codeUnitRuns[this._codeUnitRunsCount++] = new CodeUnitRun( |
|
|
|
new Range<int>(start, end), |
|
|
|
new Range<float>(this._glyphPositions[glyphPositionStyleRunStart].xPos.start, |
|
|
|
this._glyphPositions[pGlyphPositions-1].xPos.end), |
|
|
|
this._glyphPositions[pGlyphPositions - 1].xPos.end), |
|
|
|
lineNumber, TextDirection.ltr, glyphPositionStyleRunStart, textCount); |
|
|
|
|
|
|
|
lineStyleRunIndex++; |
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
this._lineHeights[lineNumber] = ((lineNumber == 0 ? 0 : this._lineHeights[lineNumber - 1]) |
|
|
|
+ Mathf.Round(maxLineSpacing + maxDescent)); |
|
|
|
+ Mathf.Round(maxLineSpacing + maxDescent)); |
|
|
|
// this._lineBaseLines[lineNumber] = this._lineHeights[lineNumber] - maxDescent;
|
|
|
|
yOffset += Mathf.Round(maxLineSpacing + preMaxDescent); |
|
|
|
preMaxDescent = maxDescent; |
|
|
|
|
|
|
int nextLineStart = lineNumber < this._lineRangeCount - 1 |
|
|
|
? this._lineRanges[lineNumber + 1].start |
|
|
|
: this._text.Length; |
|
|
|
this._glyphLines[lineNumber] = |
|
|
|
this._glyphLines[lineNumber] = |
|
|
|
new GlyphLine(glyphPositionLineStart, count, nextLineStart - lineStart); |
|
|
|
for (int i = 0; i < lineStyleRunCount; i++) { |
|
|
|
var paintRecord = this._paintRecords[this._paintRecordsCount - 1 - i]; |
|
|
|
|
|
|
for (int i = 0; i < yIndex; i++) { |
|
|
|
lineStartIndex += this._glyphLines[i].totalCountUnits; |
|
|
|
} |
|
|
|
|
|
|
|
return new PositionWithAffinity(lineStartIndex, TextAffinity.downstream); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
if (lineLimit != 0 && this._lineRangeCount >= lineLimit) { |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
var blockStart = newlineIndex > 0 ? newLinePositions[newlineIndex - 1] + 1 : 0; |
|
|
|
var blockEnd = newLinePositions[newlineIndex]; |
|
|
|
var blockSize = blockEnd - blockStart; |
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
this._resetLineBreaker(lineBreaker, blockStart, blockSize, |
|
|
|
this._resetLineBreaker(lineBreaker, blockStart, blockSize, |
|
|
|
lineLimit == 0 ? 0 : lineLimit - this._lineRangeCount); |
|
|
|
countRuns += this._addStyleRuns(lineBreaker, ref runIndex, blockStart, blockEnd); |
|
|
|
|
|
|
|