fzhangtj 6 年前
当前提交
bf51eab3
共有 7 个文件被更改,包括 181 次插入137 次删除
  1. 3
      Runtime/ui/painting/canvas.cs
  2. 7
      Runtime/ui/painting/txt/mesh_generator.cs
  3. 23
      Runtime/ui/txt/layout.cs
  4. 44
      Runtime/ui/txt/linebreaker.cs
  5. 229
      Runtime/ui/txt/paragraph.cs
  6. 6
      Runtime/ui/txt/word_separate.cs
  7. 6
      Runtime/ui/txt/wordbreaker.cs

3
Runtime/ui/painting/canvas.cs


}
public void drawRect(Rect rect, Paint paint) {
if (rect.size.isEmpty) {
return;
}
var path = new Path();
path.addRect(rect);

7
Runtime/ui/painting/txt/mesh_generator.cs


continue;
}
CharacterInfo charInfo;
font.GetCharacterInfo(ch, out charInfo, fontSizeToLoad, style.UnityFontStyle);

vertices.Add(new Vector3((float) (position.x + maxX), (float) (position.y - minY), 0));
vertices.Add(new Vector3((float) (position.x + minX), (float) (position.y - minY), 0));
if (ch == 'w') {
//Debug.Log($"{(float) (position.y - maxY)} {(float) (position.y - minY)} {charInfo.minY},{charInfo.maxY} {position.y} {charInfo.uvTopLeft}");
}
triangles.Add(baseIndex);
triangles.Add(baseIndex + 1);
triangles.Add(baseIndex + 2);

uv.Add(charInfo.uvBottomLeft);
}
if (vertices.Count == 0) {
return null;
}
MeshMesh mesh = vertices.Count > 0 ? new MeshMesh(vertices, triangles, uv) : null;
_meshes[key] = new MeshInfo(key, mesh, fontInfo.textureVersion);

23
Runtime/ui/txt/layout.cs


float _advance;
Rect _bounds;
string _text;
TabStops _tabStops;
public static float measureText(string buf, int start, int count, TextStyle style,
List<float> advances, int advanceOffset) {
public static float measureText(double offset, string buf, int start, int count, TextStyle style,
List<float> advances, int advanceOffset, TabStops tabStops) {
layout.doLayout(buf, start, count, style);
layout.setTabStops(tabStops);
layout.doLayout(offset, buf, start, count, style);
if (advances != null) {
var layoutAdv = layout.getAdvances();
for (int i = 0; i < count; i++) {

return layout.getAdvance();
}
public void doLayout(string text, int start, int count, TextStyle style) {
public void doLayout(double offset, string text, int start, int count, TextStyle style) {
this._text = text;
this._advances.Clear();
this._positions.Clear();

}
this._positions.Add(this._advance);
this._advances.Add(characterInfo.advance);
this._advance += characterInfo.advance;
float advance = characterInfo.advance;
if (ch == '\t') {
advance = this._tabStops.nextTab((float)(this._advance + offset)) - this._advance;
}
this._advances.Add(advance);
this._advance += advance;
}
public void setTabStops(TabStops tabStops) {
this._tabStops = tabStops;
}
public int nGlyphs() {

44
Runtime/ui/txt/linebreaker.cs


using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.SocialPlatforms.Impl;
int _tabWidth;
int _tabWidth = int.MaxValue;
Font _font;
int _fontSize;
const int kTabSpaceCount = 4;
List<int> _stops = new List<int>();
public void set(List<int> stops, int tabWidth) {

this._tabWidth = tabWidth;
}
public void setFont(Font font, int size) {
if (this._font != font || this._fontSize != size) {
this._tabWidth = int.MaxValue;
}
this._font = font;
this._fontSize = size;
}
public float nextTab(float widthSoFar) {
for (int i = 0; i < this._stops.Count; i++) {
if (this._stops[i] > widthSoFar) {

if (this._tabWidth == int.MaxValue) {
this._font.RequestCharactersInTexture(" ", this._fontSize);
CharacterInfo characterInfo;
this._font.GetCharacterInfo(' ' , out characterInfo, this._fontSize);
this._tabWidth = characterInfo.advance * kTabSpaceCount;
}
if (this._tabWidth == 0) {
return widthSoFar;
}
return (float)(Math.Floor(widthSoFar / this._tabWidth + 1) * this._tabWidth);
}
}

int _bestBreak;
float _bestScore;
int _spaceCount;
TabStops _tabStops = new TabStops();
TabStops _tabStops;
int mFirstTabIndex;
List<Candidate> _candidates = new List<Candidate>();

public float addStyleRun(TextStyle style, int start, int end) {
float width = 0.0f;
if (style != null) {
width = Layout.measureText(this._textBuf, start + this._textOffset, end - start, style,
this._charWidths, start);
width = Layout.measureText(this._width - this._preBreak, this._textBuf,
start + this._textOffset, end - start, style,
this._charWidths, start, this._tabStops);
var font = FontManager.instance.getOrCreate(style.fontFamily).font;
int current = this._wordBreaker.current();
int afterWord = start;
int lastBreak = start;

return this._widths;
}
public void setTabStops(List<int> stops, int tabWidth) {
this._tabStops.set(stops, tabWidth);
public void setTabStops(TabStops tabStops) {
this._tabStops = tabStops;
}
void _addWordBreak(int offset, double preBreak, double postBreak, int preSpaceCount, int postSpaceCount, float penalty) {

229
Runtime/ui/txt/paragraph.cs


using System;
using System.Collections.Generic;
using System.Linq;
using Unity.UIWidgets.foundation;
using UnityEngine;

return new Vector2d(a.x - b.x, a.y - b.y);
}
}
//flutter build ios --debug
//--local-engine-src-path /Users/fzhang/codebase/flutter/engine/src --local-engine=ios_debug_sim_unopt
// flutter clean --local-engine-src-path /Users/fzhang/codebase/flutter/engine/src --local-engine=ios_debug_sim_unopt --verbose
// flutter run --local-engine-src-path /Users/fzhang/codebase/flutter/engine/src --local-engine=ios_debug_sim_unopt
public int lineNumber;
public TextDirection direction;
public IndexRange codeUnits;
public FontMetrics fontMetrics;
public readonly int lineNumber;
public readonly TextDirection direction;
public readonly Range<int> codeUnits;
public readonly FontMetrics fontMetrics;
public List<Range<double>> positions;
public readonly List<GlyphPosition> positions;
public CodeUnitRun(IndexRange cu, int line, Range<double> xPos, FontMetrics fontMetrics, TextDirection direction) {
public CodeUnitRun(List<GlyphPosition> positions, Range<int> cu, int line, Range<double> xPos,
FontMetrics fontMetrics, TextDirection direction) {
this.positions = positions;
this.xPos.start += shift;
this.xPos.end += shift;
this.xPos = RangeUtils.shift(this.xPos, shift);
for (int i = 0; i < this.positions.Count; ++i) {
this.positions[i] = this.positions[i].shift(shift);
}
}
}

}
}
public struct IndexRange : IEquatable<IndexRange> {
public int start, end;
public IndexRange(int s, int e) {
this.start = s;
this.end = e;
}
int width() {
return this.end - this.start;
}
void shift(int delta) {
this.start += delta;
this.end += delta;
}
public bool Equals(IndexRange other) {
return this.start == other.start && this.end == other.end;
}
public override bool Equals(object obj) {
if (ReferenceEquals(null, obj)) {
return false;
}
return obj is IndexRange && this.Equals((IndexRange) obj);
}
public override int GetHashCode() {
unchecked {
return (this.start * 397) ^ this.end;
}
}
public static bool operator ==(IndexRange left, IndexRange right) {
return left.Equals(right);
}
public static bool operator !=(IndexRange left, IndexRange right) {
return !left.Equals(right);
}
}
public class LineStyleRun {
public readonly int start;
public readonly int end;

public PositionWithAffinity(int p, TextAffinity a) {
this.position = p;
this.affinity = a;
}
}
public class GlyphPosition {
public readonly Range<double> xPos;
public readonly Range<int> codeUnits;
public GlyphPosition(double start, double advance, Range<int> codeUnits) {
this.xPos = new Range<double>(start, start + advance);
this.codeUnits = codeUnits;
}
public GlyphPosition shift(double shift) {
return new GlyphPosition(this.xPos.start + shift, this.xPos.end - this.xPos.start, this.codeUnits);
}
}

return !left.Equals(right);
}
public T start, end;
public readonly T start, end;
}
public static class RangeUtils {
public static Range<double> shift(Range<double> value, double shift) {
return new Range<double>(value.start + shift, value.end + shift);
}
public readonly List<Range<double>> positions;
public readonly List<GlyphPosition> positions;
public GlyphLine(List<Range<double>> positions, int totalCountUnits) {
public GlyphLine(List<GlyphPosition> positions, int totalCountUnits) {
this.positions = positions;
this.totalCountUnits = totalCountUnits;
}

public readonly bool hardBreak;
}
const int TabSpaceCount = 4;
bool _needsLayout = true;
string _text;

List<PaintRecord> _paintRecords = new List<PaintRecord>();
List<CodeUnitRun> _codeUnitRuns = new List<CodeUnitRun>();
bool _didExceedMaxLines;
TabStops _tabStops = new TabStops();
// private double _characterWidth;

return;
}
var textStyle = this._paragraphStyle.getTextStyle();
this._tabStops.setFont(FontManager.instance.getOrCreate(textStyle.fontFamily).font, textStyle.UnityFontSize);
this._needsLayout = false;
this._width = Math.Floor(constraints.width);

double maxWordWidth = 0;
Layout layout = new Layout();
layout.setTabStops(this._tabStops);
TextBlobBuilder builder = new TextBlobBuilder();
int styleRunIndex = 0;
double yOffset = 0;

List<Range<double>> lineGlyphPositions = new List<Range<double>>();
List<Range<double>> glyphPositions = new List<Range<double>>();
List<GlyphPosition> glyphPositions = new List<GlyphPosition>();
for (int lineNumber = 0; lineNumber < lineLimit; ++lineNumber) {
var lineRange = this._lineRanges[lineNumber];

double runXOffset = 0;
double justifyXOffset = 0;
lineCodeUnitRuns.Clear();
lineGlyphPositions.Clear();
List<GlyphPosition> lineGlyphPositions = new List<GlyphPosition>();
List<PaintRecord> paintRecords = new List<PaintRecord>();
for (int i = 0; i < lineRuns.Count; ++i) {
var run = lineRuns[i];

layout.doLayout(this._text, textStart, textCount, run.style);
layout.doLayout(runXOffset, this._text, textStart, textCount, run.style);
if (layout.nGlyphs() == 0) {
continue;
}

);
float glyphAdvance = layout.getCharAdvance(glyphIndex);
glyphPositions.Add(new Range<double>(runXOffset + glyphXOffset, glyphAdvance));
glyphPositions.Add(new GlyphPosition(runXOffset + glyphXOffset, glyphAdvance,
new Range<int>(textStart + glyphIndex, textStart + glyphIndex + 1)));
// todo plus 1?
if (justifyLine) {
justifyXOffset += wordGapWidth;
}

double wordWidth = glyphPositions[glyphPositions.Count - 1].end - wordStartPosition;
double wordWidth = glyphPositions[glyphPositions.Count - 1].xPos.end - wordStartPosition;
maxWordWidth = Math.Max(wordWidth, maxWordWidth);
wordStartPosition = double.NaN;
}

builder.make(), metrics, lineNumber, layout.getAdvance()
));
lineGlyphPositions.AddRange(glyphPositions);
lineCodeUnitRuns.Add(new CodeUnitRun(new IndexRange(run.start, run.end), lineNumber,
new Range<double>(glyphPositions[0].start, glyphPositions[glyphPositions.Count - 1].end),
var codeUnitPositions = new List<GlyphPosition>(glyphPositions);
lineCodeUnitRuns.Add(new CodeUnitRun(codeUnitPositions, new Range<int>(run.start, run.end), lineNumber,
new Range<double>(glyphPositions[0].xPos.start, glyphPositions[glyphPositions.Count - 1].xPos.end),
metrics, TextDirection.ltr));
runXOffset += layout.getAdvance();

if (lineXOffset > 0) {
if (lineXOffset != 0) {
foreach (var position in lineGlyphPositions) {
position.start += lineXOffset;
position.end += lineXOffset;
for (int i = 0; i < lineGlyphPositions.Count; ++i) {
lineGlyphPositions[i] = lineGlyphPositions[i].shift(lineXOffset);
}
}

}
var baseLine = this._lineBaseLines[run.lineNumber];
double top = baseLine - run.fontMetrics.ascent;
double top = baseLine + run.fontMetrics.ascent;
double left, right;
if (run.codeUnits.start >= start && run.codeUnits.end <= end) {
left = run.xPos.start;
right = run.xPos.end;
}
else {
left = double.MaxValue;
right = double.MinValue;
foreach (var gp in run.positions) {
if (gp.codeUnits.start >= start && gp.codeUnits.end <= end) {
left = Math.Min(left, gp.xPos.start);
right = Math.Max(right, gp.xPos.end);
}
}
var from = Math.Max(start, run.codeUnits.start);
var to = Math.Min(end, run.codeUnits.end);
if (from < to) {
List<TextBox> boxs;
if (!lineBoxes.TryGetValue(run.lineNumber, out boxs)) {
boxs = new List<TextBox>();
lineBoxes.Add(run.lineNumber, boxs);
if (left == Double.MaxValue || right == Double.MinValue) {
continue;
double left = this._characterPositions[from].x;
double right = this._characterPositions[to - 1].x + this._characterWidths[to - 1];
boxs.Add(TextBox.fromLTBD(left, top, right, bottom, run.direction));
}
List<TextBox> boxs;
if (!lineBoxes.TryGetValue(run.lineNumber, out boxs)) {
boxs = new List<TextBox>();
lineBoxes.Add(run.lineNumber, boxs);
boxs.Add(TextBox.fromLTBD(left, top, right, bottom, run.direction));
}
for (int lineNumber = 0; lineNumber < this._lineRanges.Count; ++lineNumber) {

}
}
var line = this._lineRanges[yIndex];
if (line.start >= line.end) {
return new PositionWithAffinity(line.start, TextAffinity.downstream);
var lineGlyphPosition = this._glyphLines[yIndex].positions;
if (lineGlyphPosition.Count == 0) {
int lineStartIndex = this._glyphLines.Where((g, i) => i < yIndex).Sum((gl) => gl.totalCountUnits);
return new PositionWithAffinity(lineStartIndex, TextAffinity.downstream);
int index;
for (index = line.start; index < line.end; ++index) {
if (dx < this._characterPositions[index].x + this._characterWidths[index]) {
GlyphPosition gp = null;
for (int xIndex = 0; xIndex < lineGlyphPosition.Count; ++xIndex) {
double glyphEnd = xIndex < lineGlyphPosition.Count - 1
? lineGlyphPosition[xIndex + 1].xPos.start
: lineGlyphPosition[xIndex].xPos.end;
if (dx < glyphEnd) {
gp = lineGlyphPosition[xIndex];
if (index >= line.end) {
return new PositionWithAffinity(line.end, TextAffinity.upstream);
if (gp == null) {
GlyphPosition lastGlyph = lineGlyphPosition[lineGlyphPosition.Count - 1];
return new PositionWithAffinity(lastGlyph.codeUnits.end, TextAffinity.upstream);
var codeUnit = this._codeUnitRuns.Find((u) => u.codeUnits.start >= index && index < u.codeUnits.end);
if (codeUnit != null) {
direction = codeUnit.direction;
foreach (var run in this._codeUnitRuns) {
if (gp.codeUnits.start >= run.codeUnits.start && gp.codeUnits.end <= run.codeUnits.end) {
direction = run.direction;
break;
}
double glyphCenter = (this._characterPositions[index].x + this._characterPositions[index].x +
this._characterWidths[index]) / 2;
double glyphCenter = (gp.xPos.start + gp.xPos.end) / 2;
return new PositionWithAffinity(index, TextAffinity.downstream);
return new PositionWithAffinity(gp.codeUnits.start, TextAffinity.downstream);
return new PositionWithAffinity(index + 1, TextAffinity.upstream);
return new PositionWithAffinity(gp.codeUnits.end, TextAffinity.upstream);
}
}

return this._lineRanges[lineIndex];
}
public IndexRange getWordBoundary(int offset) {
public Range<int> getWordBoundary(int offset) {
public static void offsetCharacters(Vector2d offset, Vector2d[] characterPos, int start, int end) {
if (characterPos != null) {
for (int i = start; i < characterPos.Length && i < end; ++i) {
characterPos[i] = characterPos[i] + offset;
}
}
}
this._lineRanges.Clear();
this._lineWidths.Clear();
this._maxIntrinsicWidth = 0;
var newLinePositions = new List<int>();
for (var i = 0; i < this._text.Length; i++) {
if (this._text[i] == '\n') {

lineBreaker.setLineWidth((float)this._width);
lineBreaker.resize(blockSize);
lineBreaker.setTabStops(null, 14);
lineBreaker.setTabStops(this._tabStops);
lineBreaker.setText(this._text, blockStart, blockSize);
while (runIndex < this._runs.size) {

}
if (decoration != null && decoration.contains(TextDecoration.overline)) {
yOffset -= metrics.ascent;
yOffset = metrics.ascent;
canvas.drawLine(new Offset(x, y + yOffset), new Offset(x + width, y + yOffset), paint);
yOffset = yOffsetOriginal;
}

6
Runtime/ui/txt/word_separate.cs


this._text = text;
}
public IndexRange findWordRange(int index) {
public Range<int> findWordRange(int index) {
return new IndexRange(0, 0);
return new Range<int>(0, 0);
}
var t = this.classifyChar(index);
int start = index;

end = i;
}
}
return new IndexRange(start, end + 1);
return new Range<int>(start, end + 1);
}

6
Runtime/ui/txt/wordbreaker.cs


while (result < this._current) {
int ix = result;
uint c = nextCode(this._text, ref ix, this._current);
if (!LayoutUtils.isLineEndSpace((char) c)) { // todo
if (!LayoutUtils.isLineEndSpace((char) c)) {
break;
}

int result = this._current;
while (result > this._last) {
int ix = result;
uint ch = preCode(_text, ref ix, this._last);
if (!LayoutUtils.isLineEndSpace((char) ch)) { // todo
uint ch = preCode(this._text, ref ix, this._last);
if (!LayoutUtils.isLineEndSpace((char) ch)) {
break;
}

正在加载...
取消
保存