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

Commit c7dc43a

Browse files
authored
Merge pull request #261 from UnityTech/layout
Layout
2 parents 1a91397 + e56b8c9 commit c7dc43a

30 files changed

+2997
-2162
lines changed

Runtime/painting/text_painter.cs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ public TextPainter(TextSpan text = null,
3434
this._ellipsis = ellipsis;
3535
}
3636

37-
3837
public float textScaleFactor {
3938
get { return this._textScaleFactor; }
4039
set {
@@ -43,9 +42,9 @@ public float textScaleFactor {
4342
}
4443

4544
this._textScaleFactor = value;
46-
this._paragraph = null;
4745
this._layoutTemplate = null;
4846
this._needsLayout = true;
47+
Paragraph.release(ref this._paragraph);
4948
}
5049
}
5150

@@ -57,7 +56,7 @@ public string ellipsis {
5756
}
5857

5958
this._ellipsis = value;
60-
this._paragraph = null;
59+
Paragraph.release(ref this._paragraph);
6160
this._needsLayout = true;
6261
}
6362
}
@@ -74,7 +73,7 @@ public TextSpan text {
7473
}
7574

7675
this._text = value;
77-
this._paragraph = null;
76+
Paragraph.release(ref this._paragraph);
7877
this._needsLayout = true;
7978
}
8079
}
@@ -94,7 +93,7 @@ public TextDirection? textDirection {
9493
}
9594

9695
this._textDirection = value;
97-
this._paragraph = null;
96+
Paragraph.release(ref this._paragraph);
9897
this._layoutTemplate = null;
9998
this._needsLayout = true;
10099
}
@@ -108,7 +107,7 @@ public TextAlign textAlign {
108107
}
109108

110109
this._textAlign = value;
111-
this._paragraph = null;
110+
Paragraph.release(ref this._paragraph);
112111
this._needsLayout = true;
113112
}
114113
}
@@ -128,7 +127,7 @@ public int? maxLines {
128127
}
129128

130129
this._maxLines = value;
131-
this._paragraph = null;
130+
Paragraph.release(ref this._paragraph);
132131
this._needsLayout = true;
133132
}
134133
}
@@ -213,9 +212,9 @@ public Offset getOffsetForCaret(TextPosition position, Rect caretPrototype) {
213212
var prevCodeUnit = this._text.codeUnitAt(offset);
214213
if (prevCodeUnit == null) // out of upper bounds
215214
{
216-
var rectNextLine = this._paragraph.getNextLineStartRect();
217-
if (rectNextLine != null) {
218-
return new Offset(rectNextLine.start, rectNextLine.top);
215+
var rectNextLineTop = this._paragraph.getNextLineStartRectTop();
216+
if (rectNextLineTop != null) {
217+
return new Offset(0, rectNextLineTop.Value);
219218
}
220219
}
221220
}

Runtime/rendering/editable.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -881,14 +881,14 @@ public TextPosition getParagraphEnd(TextPosition position, TextAffinity? affinit
881881

882882
public TextPosition getParagraphForward(TextPosition position, TextAffinity? affinity = null) {
883883
var lineCount = this._textPainter.getLineCount();
884-
Paragraph.LineRange line = null;
884+
Paragraph.LineRange? line = null;
885885
for (int i = 0; i < lineCount; ++i) {
886886
line = this._textPainter.getLineRange(i);
887-
if (!line.hardBreak) {
887+
if (!line.Value.hardBreak) {
888888
continue;
889889
}
890890

891-
if (line.end > position.offset) {
891+
if (line.Value.end > position.offset) {
892892
break;
893893
}
894894
}
@@ -897,21 +897,21 @@ public TextPosition getParagraphForward(TextPosition position, TextAffinity? aff
897897
return new TextPosition(position.offset, affinity ?? position.affinity);
898898
}
899899

900-
return new TextPosition(line.end, affinity ?? position.affinity);
900+
return new TextPosition(line.Value.end, affinity ?? position.affinity);
901901
}
902902

903903

904904
public TextPosition getParagraphBackward(TextPosition position, TextAffinity? affinity = null) {
905905
var lineCount = this._textPainter.getLineCount();
906906

907-
Paragraph.LineRange line = null;
907+
Paragraph.LineRange? line = null;
908908
for (int i = lineCount - 1; i >= 0; --i) {
909909
line = this._textPainter.getLineRange(i);
910910
if (i != 0 && !this._textPainter.getLineRange(i - 1).hardBreak) {
911911
continue;
912912
}
913913

914-
if (line.start < position.offset) {
914+
if (line.Value.start < position.offset) {
915915
break;
916916
}
917917
}
@@ -920,7 +920,7 @@ public TextPosition getParagraphBackward(TextPosition position, TextAffinity? af
920920
return new TextPosition(position.offset, affinity ?? position.affinity);
921921
}
922922

923-
return new TextPosition(line.start, affinity ?? position.affinity);
923+
return new TextPosition(line.Value.start, affinity ?? position.affinity);
924924
}
925925

926926
protected override float computeMinIntrinsicWidth(float height) {

Runtime/ui/painting/draw_cmd.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public class DrawPicture : DrawCmd {
8787
}
8888

8989
public class DrawTextBlob : DrawCmd {
90-
public TextBlob textBlob;
90+
public TextBlob? textBlob;
9191
public Offset offset;
9292
public Paint paint;
9393
}

Runtime/ui/painting/picture.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ public void addDrawCmd(DrawCmd drawCmd) {
268268
case DrawTextBlob cmd: {
269269
var state = this._getState();
270270
var scale = XformUtils.getScale(state.xform);
271-
var rect = cmd.textBlob.boundsInText.shift(cmd.offset);
271+
var rect = cmd.textBlob.Value.shiftedBoundsInText(cmd.offset.dx, cmd.offset.dy);
272272
rect = state.xform.mapRect(rect);
273273

274274
var paint = cmd.paint;

Runtime/ui/painting/txt/mesh_generator.cs

Lines changed: 51 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ class MeshKey : PoolObject, IEquatable<MeshKey> {
99
public float scale;
1010

1111
public MeshKey() {
12-
1312
}
1413

1514
public static MeshKey create(long textBlobId, float scale) {
@@ -73,7 +72,6 @@ class MeshInfo : PoolObject {
7372
long _timeToLive;
7473

7574
public MeshInfo() {
76-
7775
}
7876

7977
public static MeshInfo create(MeshKey key, uiMeshMesh mesh, long textureVersion, int timeToLive = 5) {
@@ -99,27 +97,26 @@ public void touch(long timeTolive = 5) {
9997
}
10098
}
10199

102-
100+
103101
class TextBlobMesh : PoolObject {
104-
105102
static readonly Dictionary<MeshKey, MeshInfo> _meshes = new Dictionary<MeshKey, MeshInfo>();
106103
static long _frameCount = 0;
107-
108-
public TextBlob textBlob;
104+
105+
public TextBlob? textBlob;
109106
public float scale;
110107
public uiMatrix3 matrix;
111-
108+
112109
uiMeshMesh _mesh;
113110
bool _resolved;
114111

115112
public TextBlobMesh() {
116113
}
117114

118115
public override void clear() {
119-
this.textBlob = null;
120116
ObjectPool<uiMeshMesh>.release(this._mesh);
121117
this._mesh = null;
122118
this._resolved = false;
119+
this.textBlob = null;
123120
}
124121

125122
public static TextBlobMesh create(TextBlob textBlob, float scale, uiMatrix3 matrix) {
@@ -129,7 +126,7 @@ public static TextBlobMesh create(TextBlob textBlob, float scale, uiMatrix3 matr
129126
newMesh.matrix = matrix;
130127
return newMesh;
131128
}
132-
129+
133130
public static long frameCount {
134131
get { return _frameCount; }
135132
}
@@ -139,6 +136,7 @@ public static int meshCount {
139136
}
140137

141138
static List<MeshKey> _keysToRemove = new List<MeshKey>();
139+
142140
public static void tickNextFrame() {
143141
_frameCount++;
144142
D.assert(_keysToRemove.Count == 0);
@@ -148,11 +146,11 @@ public static void tickNextFrame() {
148146
}
149147
}
150148

151-
foreach (var key in _keysToRemove)
152-
{
149+
foreach (var key in _keysToRemove) {
153150
ObjectPool<MeshInfo>.release(_meshes[key]);
154151
_meshes.Remove(key);
155152
}
153+
156154
_keysToRemove.Clear();
157155
}
158156

@@ -162,58 +160,59 @@ public uiMeshMesh resolveMesh() {
162160
}
163161

164162
this._resolved = true;
165-
166-
var style = this.textBlob.style;
167-
168-
var text = this.textBlob.text;
169-
var key = MeshKey.create(this.textBlob.instanceId, this.scale);
163+
164+
var style = this.textBlob.Value.style;
165+
166+
var text = this.textBlob.Value.text;
167+
var key = MeshKey.create(this.textBlob.Value.instanceId, this.scale);
170168
var fontInfo = FontManager.instance.getOrCreate(style.fontFamily, style.fontWeight, style.fontStyle);
171169
var font = fontInfo.font;
172-
170+
173171
_meshes.TryGetValue(key, out var meshInfo);
174172
if (meshInfo != null && meshInfo.textureVersion == fontInfo.textureVersion) {
175173
ObjectPool<MeshKey>.release(key);
176174
meshInfo.touch();
177175
this._mesh = meshInfo.mesh.transform(this.matrix);
178176
return this._mesh;
179177
}
180-
178+
181179
// Handling Emoji
182-
char startingChar = text[this.textBlob.textOffset];
180+
char startingChar = text[this.textBlob.Value.textOffset];
183181
if (char.IsHighSurrogate(startingChar) || EmojiUtils.isSingleCharEmoji(startingChar)) {
184182
var vert = ObjectPool<uiList<Vector3>>.alloc();
185183
var tri = ObjectPool<uiList<int>>.alloc();
186184
var uvCoord = ObjectPool<uiList<Vector2>>.alloc();
187-
185+
188186
var metrics = FontMetrics.fromFont(font, style.UnityFontSize);
189187
var minMaxRect = EmojiUtils.getMinMaxRect(style.fontSize, metrics.ascent, metrics.descent);
190188
var minX = minMaxRect.left;
191189
var maxX = minMaxRect.right;
192190
var minY = minMaxRect.top;
193191
var maxY = minMaxRect.bottom;
194192

195-
for (int i = 0; i < this.textBlob.textSize; i++) {
196-
char a = text[this.textBlob.textOffset + i];
193+
for (int i = 0; i < this.textBlob.Value.textSize; i++) {
194+
char a = text[this.textBlob.Value.textOffset + i];
197195
int code = a;
198196
if (char.IsHighSurrogate(a)) {
199-
D.assert(i+1 < this.textBlob.textSize);
200-
D.assert(this.textBlob.textOffset+i+1 < this.textBlob.text.Length);
201-
char b = text[this.textBlob.textOffset+i+1];
197+
D.assert(i + 1 < this.textBlob.Value.textSize);
198+
D.assert(this.textBlob.Value.textOffset + i + 1 < this.textBlob.Value.text.Length);
199+
char b = text[this.textBlob.Value.textOffset + i + 1];
202200
D.assert(char.IsLowSurrogate(b));
203201
code = char.ConvertToUtf32(a, b);
204-
} else if (char.IsLowSurrogate(a) || EmojiUtils.isEmptyEmoji(a)) {
202+
}
203+
else if (char.IsLowSurrogate(a) || EmojiUtils.isEmptyEmoji(a)) {
205204
continue;
206205
}
206+
207207
var uvRect = EmojiUtils.getUVRect(code);
208208

209-
var pos = this.textBlob.positions[i];
209+
var positionX = this.textBlob.Value.getPositionX(i);
210210

211211
int baseIndex = vert.Count;
212-
vert.Add(new Vector3(pos.x + minX, pos.y + minY, 0));
213-
vert.Add(new Vector3(pos.x + maxX, pos.y + minY, 0));
214-
vert.Add(new Vector3(pos.x + maxX, pos.y + maxY, 0));
215-
vert.Add(new Vector3(pos.x + minX, pos.y + maxY, 0));
216-
212+
vert.Add(new Vector3(positionX + minX, minY, 0));
213+
vert.Add(new Vector3(positionX + maxX, minY, 0));
214+
vert.Add(new Vector3(positionX + maxX, maxY, 0));
215+
vert.Add(new Vector3(positionX + minX, maxY, 0));
217216
tri.Add(baseIndex);
218217
tri.Add(baseIndex + 1);
219218
tri.Add(baseIndex + 2);
@@ -225,58 +224,61 @@ public uiMeshMesh resolveMesh() {
225224
uvCoord.Add(uvRect.topRight.toVector());
226225
uvCoord.Add(uvRect.topLeft.toVector());
227226

228-
if(char.IsHighSurrogate(a)) i++;
227+
if (char.IsHighSurrogate(a)) {
228+
i++;
229+
}
229230
}
230-
231+
231232
uiMeshMesh meshMesh = uiMeshMesh.create(null, vert, tri, uvCoord);
232-
233+
233234
if (_meshes.ContainsKey(key)) {
234235
ObjectPool<MeshInfo>.release(_meshes[key]);
235236
_meshes.Remove(key);
236237
}
238+
237239
_meshes[key] = MeshInfo.create(key, meshMesh, 0);
238240

239241
this._mesh = meshMesh.transform(this.matrix);
240242
return this._mesh;
241243
}
242-
243-
var length = this.textBlob.textSize;
244+
245+
var length = this.textBlob.Value.textSize;
244246
var fontSizeToLoad = Mathf.CeilToInt(style.UnityFontSize * this.scale);
245247

246248
var vertices = ObjectPool<uiList<Vector3>>.alloc();
247249
vertices.SetCapacity(length * 4);
248-
250+
249251
var triangles = ObjectPool<uiList<int>>.alloc();
250252
triangles.SetCapacity(length * 6);
251253

252254
var uv = ObjectPool<uiList<Vector2>>.alloc();
253255
uv.SetCapacity(length * 4);
254-
256+
255257
for (int charIndex = 0; charIndex < length; ++charIndex) {
256-
var ch = text[charIndex + this.textBlob.textOffset];
258+
var ch = text[charIndex + this.textBlob.Value.textOffset];
257259
// first char as origin for mesh position
258-
var position = this.textBlob.positions[charIndex];
260+
var positionX = this.textBlob.Value.getPositionX(charIndex);
259261
if (LayoutUtils.isWordSpace(ch) || LayoutUtils.isLineEndSpace(ch) || ch == '\t') {
260262
continue;
261263
}
262264

263265
if (fontSizeToLoad == 0) {
264266
continue;
265267
}
266-
268+
267269
font.getGlyphInfo(ch, out var glyphInfo, fontSizeToLoad, style.UnityFontStyle);
268-
270+
269271
var minX = glyphInfo.minX / this.scale;
270272
var maxX = glyphInfo.maxX / this.scale;
271273
var minY = -glyphInfo.maxY / this.scale;
272274
var maxY = -glyphInfo.minY / this.scale;
273275

274276
var baseIndex = vertices.Count;
275277

276-
vertices.Add(new Vector3((position.x + minX), (position.y + minY), 0));
277-
vertices.Add(new Vector3((position.x + maxX), (position.y + minY), 0));
278-
vertices.Add(new Vector3((position.x + maxX), (position.y + maxY), 0));
279-
vertices.Add(new Vector3((position.x + minX), (position.y + maxY), 0));
278+
vertices.Add(new Vector3(positionX + minX, minY, 0));
279+
vertices.Add(new Vector3(positionX + maxX, minY, 0));
280+
vertices.Add(new Vector3(positionX + maxX, maxY, 0));
281+
vertices.Add(new Vector3(positionX + minX, maxY, 0));
280282

281283
triangles.Add(baseIndex);
282284
triangles.Add(baseIndex + 1);
@@ -301,11 +303,12 @@ public uiMeshMesh resolveMesh() {
301303
}
302304

303305
uiMeshMesh mesh = vertices.Count > 0 ? uiMeshMesh.create(null, vertices, triangles, uv) : null;
304-
306+
305307
if (_meshes.ContainsKey(key)) {
306308
ObjectPool<MeshInfo>.release(_meshes[key]);
307309
_meshes.Remove(key);
308310
}
311+
309312
_meshes[key] = MeshInfo.create(key, mesh, fontInfo.textureVersion);
310313

311314
this._mesh = mesh.transform(this.matrix);

0 commit comments

Comments
 (0)