|
|
|
|
|
|
int _lineCount; |
|
|
|
int _paintRecordsCount; |
|
|
|
int _codeUnitRunsCount; |
|
|
|
int _lineRangeCount; |
|
|
|
int _lineWidthCount; |
|
|
|
bool _didExceedMaxLines; |
|
|
|
TabStops _tabStops = new TabStops(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int lineStyleRunsCount = this._computeLineBreak(); |
|
|
|
|
|
|
|
if (this._glyphLines == null || this._glyphLines.Length < this._lineRanges.Count) { |
|
|
|
this._glyphLines = new GlyphLine[this._lineRanges.Count]; |
|
|
|
if (this._glyphLines == null || this._glyphLines.Length < this._lineRangeCount) { |
|
|
|
this._glyphLines = new GlyphLine[LayoutUtils.minPowerOfTwo(this._lineRangeCount)]; |
|
|
|
// if (this._lineBaseLines == null || this._lineBaseLines.Length < this._lineRanges.Count) {
|
|
|
|
// this._lineBaseLines = new float[this._lineRanges.Count];
|
|
|
|
// if (this._lineBaseLines == null || this._lineBaseLines.Length < this._lineRangeCount) {
|
|
|
|
// this._lineBaseLines = new float[this._lineRangeCount];
|
|
|
|
if (this._lineHeights == null || this._lineHeights.Length < this._lineRanges.Count) { |
|
|
|
this._lineHeights = new float[this._lineRanges.Count]; |
|
|
|
if (this._lineHeights == null || this._lineHeights.Length < this._lineRangeCount) { |
|
|
|
this._lineHeights = new float[LayoutUtils.minPowerOfTwo(this._lineRangeCount)]; |
|
|
|
this._paintRecords = new PaintRecord[lineStyleRunsCount]; |
|
|
|
this._paintRecords = new PaintRecord[LayoutUtils.minPowerOfTwo(lineStyleRunsCount)]; |
|
|
|
this._codeUnitRuns = new CodeUnitRun[lineStyleRunsCount]; |
|
|
|
this._codeUnitRuns = new CodeUnitRun[LayoutUtils.minPowerOfTwo(lineStyleRunsCount)]; |
|
|
|
this._didExceedMaxLines = this._lineRanges.Count > styleMaxLines; |
|
|
|
this._didExceedMaxLines = this._lineRangeCount > styleMaxLines; |
|
|
|
var lineLimit = Mathf.Min(styleMaxLines, this._lineRanges.Count); |
|
|
|
var lineLimit = Mathf.Min(styleMaxLines, this._lineRangeCount); |
|
|
|
int styleRunIndex = 0; |
|
|
|
float yOffset = 0; |
|
|
|
float preMaxDescent = 0; |
|
|
|
|
|
|
|
|
|
|
// All text blobs share a single position buffer, which is big enough taking ellipsis into consideration
|
|
|
|
if (this._textBlobPositions == null || this._textBlobPositions.Length < ellipsizedLength) { |
|
|
|
this._textBlobPositions = new float[ellipsizedLength]; |
|
|
|
this._textBlobPositions = new float[LayoutUtils.minPowerOfTwo(ellipsizedLength)]; |
|
|
|
this._glyphPositions = new GlyphPosition[ellipsizedLength]; |
|
|
|
this._glyphPositions = new GlyphPosition[LayoutUtils.minPowerOfTwo(ellipsizedLength)]; |
|
|
|
} |
|
|
|
|
|
|
|
// Pointer to the _glyphPositions array, to keep track of where the next glyph is stored
|
|
|
|
|
|
|
// TODO: find a way to compute the maxTextCount for the entire paragraph, so that this allocation
|
|
|
|
// happens only once
|
|
|
|
if (_advancesBuffer == null || _advancesBuffer.Length < maxTextCount) { |
|
|
|
_advancesBuffer = new float[maxTextCount]; |
|
|
|
_advancesBuffer = new float[LayoutUtils.minPowerOfTwo(maxTextCount)]; |
|
|
|
_positionsBuffer = new float[maxTextCount]; |
|
|
|
_positionsBuffer = new float[LayoutUtils.minPowerOfTwo(maxTextCount)]; |
|
|
|
} |
|
|
|
|
|
|
|
// Keep of the position in _glyphPositions before evaluating this line
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
int lineStart = lineRange.start; |
|
|
|
int nextLineStart = lineNumber < this._lineRanges.Count - 1 |
|
|
|
int nextLineStart = lineNumber < this._lineRangeCount - 1 |
|
|
|
? this._lineRanges[lineNumber + 1].start |
|
|
|
: this._text.Length; |
|
|
|
this._glyphLines[lineNumber] = |
|
|
|
|
|
|
this._lineCount = lineLimit; |
|
|
|
this._maxIntrinsicWidth = 0; |
|
|
|
float lineBlockWidth = 0; |
|
|
|
for (int i = 0; i < this._lineWidths.Count; ++i) { |
|
|
|
for (int i = 0; i < this._lineWidthCount; ++i) { |
|
|
|
lineBlockWidth += this._lineWidths[i]; |
|
|
|
if (this._lineRanges[i].hardBreak) { |
|
|
|
this._maxIntrinsicWidth = Mathf.Max(lineBlockWidth, this._maxIntrinsicWidth); |
|
|
|
|
|
|
boxs.Add(TextBox.fromLTBD(left, top, right, bottom, run.direction)); |
|
|
|
} |
|
|
|
|
|
|
|
for (int lineNumber = 0; lineNumber < this._lineRanges.Count; ++lineNumber) { |
|
|
|
for (int lineNumber = 0; lineNumber < this._lineRangeCount; ++lineNumber) { |
|
|
|
var line = this._lineRanges[lineNumber]; |
|
|
|
if (line.start >= end) { |
|
|
|
break; |
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
int _computeLineBreak() { |
|
|
|
this._lineRanges.Clear(); |
|
|
|
this._lineWidths.Clear(); |
|
|
|
this._lineRangeCount = 0; |
|
|
|
this._lineWidthCount = 0; |
|
|
|
this._maxIntrinsicWidth = 0; |
|
|
|
|
|
|
|
int lineLimit = this._paragraphStyle.ellipsized() |
|
|
|
|
|
|
int runIndex = 0; |
|
|
|
int countRuns = 0; |
|
|
|
for (var newlineIndex = 0; newlineIndex < newLineCount; ++newlineIndex) { |
|
|
|
if (lineLimit != 0 && this._lineRanges.Count >= lineLimit) { |
|
|
|
if (lineLimit != 0 && this._lineRangeCount >= lineLimit) { |
|
|
|
break; |
|
|
|
} |
|
|
|
var blockStart = newlineIndex > 0 ? newLinePositions[newlineIndex - 1] + 1 : 0; |
|
|
|
|
|
|
this._addEmptyLine(blockStart, blockEnd); |
|
|
|
continue; |
|
|
|
} |
|
|
|
if (lineLimit != 0 && this._lineRanges.Count >= lineLimit) { |
|
|
|
if (lineLimit != 0 && this._lineRangeCount >= lineLimit) { |
|
|
|
lineLimit == 0 ? 0 : lineLimit - this._lineRanges.Count); |
|
|
|
lineLimit == 0 ? 0 : lineLimit - this._lineRangeCount); |
|
|
|
countRuns += this._addStyleRuns(lineBreaker, ref runIndex, blockStart, blockEnd); |
|
|
|
|
|
|
|
int breaksCount = lineBreaker.computeBreaks(); |
|
|
|
|
|
|
return countRuns; |
|
|
|
} |
|
|
|
|
|
|
|
void _addLineRangeAndWidth(LineRange lineRange, float width) { |
|
|
|
if (this._lineRanges.Count <= this._lineRangeCount) { |
|
|
|
this._lineRanges.Add(lineRange); |
|
|
|
this._lineRangeCount++; |
|
|
|
} |
|
|
|
else { |
|
|
|
this._lineRanges[this._lineRangeCount++] = lineRange; |
|
|
|
} |
|
|
|
|
|
|
|
if (this._lineWidths.Count <= this._lineWidthCount) { |
|
|
|
this._lineWidths.Add(width); |
|
|
|
this._lineWidthCount++; |
|
|
|
} |
|
|
|
else { |
|
|
|
this._lineWidths[this._lineWidthCount++] = width; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
this._lineRanges.Add(new LineRange(blockStart, blockEnd, blockEnd, |
|
|
|
blockEnd < this._text.Length ? blockEnd + 1 : blockEnd, true)); |
|
|
|
this._lineWidths.Add(0); |
|
|
|
this._addLineRangeAndWidth(new LineRange(blockStart, blockEnd, blockEnd, |
|
|
|
blockEnd < this._text.Length ? blockEnd + 1 : blockEnd, true), 0); |
|
|
|
} |
|
|
|
|
|
|
|
void _resetLineBreaker(LineBreaker lineBreaker, int blockStart, int blockSize, int lineLimit) { |
|
|
|
|
|
|
lineEndExcludingWhitespace--; |
|
|
|
} |
|
|
|
|
|
|
|
this._lineRanges.Add(new LineRange(lineStart, lineEnd, |
|
|
|
lineEndExcludingWhitespace, lineEndIncludingNewline, hardBreak)); |
|
|
|
this._lineWidths.Add(lineBreaker.getWidth(i)); |
|
|
|
this._addLineRangeAndWidth(new LineRange(lineStart, lineEnd, |
|
|
|
lineEndExcludingWhitespace, lineEndIncludingNewline, hardBreak), lineBreaker.getWidth(i)); |
|
|
|
for (int lineNumber = 0; lineNumber < this._lineRanges.Count; lineNumber++) { |
|
|
|
for (int lineNumber = 0; lineNumber < this._lineRangeCount; lineNumber++) { |
|
|
|
var inWord = false; |
|
|
|
int wordCount = 0, start = this._lineRanges[lineNumber].start, end = this._lineRanges[lineNumber].end; |
|
|
|
for (int i = start; i < end; ++i) { |
|
|
|