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

Commit 9360525

Browse files
author
Yuncong Zhang
committed
Render continuous emojis in one draw call.
1 parent 4124a88 commit 9360525

File tree

3 files changed

+93
-78
lines changed

3 files changed

+93
-78
lines changed

Runtime/ui/painting/txt/mesh_generator.cs

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -140,37 +140,41 @@ public MeshMesh resolveMesh() {
140140
var font = fontInfo.font;
141141

142142
if (char.IsHighSurrogate(text[this.textBlob.textOffset])) {
143-
D.assert(this.textBlob.textSize == 2);
144-
145-
char a = text[this.textBlob.textOffset], b = text[this.textBlob.textOffset+1];
146-
D.assert(char.IsLowSurrogate(b));
147-
148-
var pos = this.textBlob.positions[0];
143+
D.assert(this.textBlob.textSize % 2 == 0);
144+
var vert = new List<Vector3>();
145+
var tri = new List<int>();
146+
var uvCoord = new List<Vector2>();
149147
var metrics = FontMetrics.fromFont(font, style.UnityFontSize);
150-
151148
var minMaxRect = EmojiUtils.getMinMaxRect(style.fontSize, metrics.ascent, metrics.descent);
152149
var minX = minMaxRect.left;
153150
var maxX = minMaxRect.right;
154151
var minY = minMaxRect.top;
155152
var maxY = minMaxRect.bottom;
156-
157-
var vert = new List<Vector3> {
158-
new Vector3(pos.x + minX, pos.y + minY, 0),
159-
new Vector3(pos.x + maxX, pos.y + minY, 0),
160-
new Vector3(pos.x + maxX, pos.y + maxY, 0),
161-
new Vector3(pos.x + minX, pos.y + maxY, 0),
162-
};
163-
var tri = new List<int> {
164-
0, 1, 2, 0, 2, 3,
165-
};
166-
var code = char.ConvertToUtf32(a, b);
167-
var uvRect = EmojiUtils.getUVRect(code);
168-
var uvCoord = new List<Vector2> {
169-
uvRect.bottomLeft.toVector(),
170-
uvRect.bottomRight.toVector(),
171-
uvRect.topRight.toVector(),
172-
uvRect.topLeft.toVector(),
173-
};
153+
154+
for (int i = 0; i < this.textBlob.textSize; i += 2) {
155+
char a = text[this.textBlob.textOffset+i], b = text[this.textBlob.textOffset+i+1];
156+
D.assert(char.IsLowSurrogate(b));
157+
158+
var pos = this.textBlob.positions[i];
159+
160+
vert.Add(new Vector3(pos.x + minX, pos.y + minY, 0));
161+
vert.Add(new Vector3(pos.x + maxX, pos.y + minY, 0));
162+
vert.Add(new Vector3(pos.x + maxX, pos.y + maxY, 0));
163+
vert.Add(new Vector3(pos.x + minX, pos.y + maxY, 0));
164+
165+
tri.Add(i * 2);
166+
tri.Add(i * 2 + 1);
167+
tri.Add(i * 2 + 2);
168+
tri.Add(i * 2);
169+
tri.Add(i * 2 + 2);
170+
tri.Add(i * 2 + 3);
171+
var code = char.ConvertToUtf32(a, b);
172+
var uvRect = EmojiUtils.getUVRect(code);
173+
uvCoord.Add(uvRect.bottomLeft.toVector());
174+
uvCoord.Add(uvRect.bottomRight.toVector());
175+
uvCoord.Add(uvRect.topRight.toVector());
176+
uvCoord.Add(uvRect.topLeft.toVector());
177+
}
174178
MeshMesh meshMesh = new MeshMesh(null, vert, tri, uvCoord);
175179
_meshes[key] = new MeshInfo(key, meshMesh, 0);
176180

Runtime/ui/txt/emoji.cs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,16 +64,28 @@ public static Rect getUVRect(int code) {
6464

6565
public static List<string> splitBySurrogatePair(string text) {
6666
int start = 0;
67+
bool? currentSurrogate = null;
6768
List<string> list = new List<string>();
69+
6870
for (int i = 0; i < text.Length; i++) {
6971
if (i < text.Length - 1 && char.IsHighSurrogate(text[i]) && char.IsLowSurrogate(text[i + 1])) {
70-
if (i > start) {
71-
list.Add(text.Substring(start, i - start));
72+
if (currentSurrogate != true) {
73+
if (i > start) {
74+
list.Add(text.Substring(start, i - start));
75+
start = i;
76+
}
7277
}
73-
74-
start = i + 2;
75-
list.Add(text.Substring(i, 2));
7678
i++;
79+
currentSurrogate = true;
80+
}
81+
else {
82+
if (currentSurrogate != false) {
83+
if (i > start) {
84+
list.Add(text.Substring(start, i - start));
85+
start = i;
86+
}
87+
}
88+
currentSurrogate = false;
7789
}
7890
}
7991

Runtime/ui/txt/layout.cs

Lines changed: 47 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,7 @@ public void doLayout(float offset, TextBuff buff, int start, int count, TextStyl
4141
Font font = FontManager.instance.getOrCreate(style.fontFamily, style.fontWeight, style.fontStyle).font;
4242

4343
if (char.IsHighSurrogate(buff.text[buff.offset + start])) {
44-
D.assert(count == 2);
45-
D.assert(char.IsLowSurrogate(buff.text[buff.offset + start+1]));
46-
47-
this.layoutEmoji(style, font);
44+
this.layoutEmoji(style, font, start, count);
4845
}
4946
else {
5047
font.RequestCharactersInTextureSafe(buff.text, style.UnityFontSize, style.UnityFontStyle);
@@ -127,52 +124,54 @@ void layoutWord(float offset, int layoutOffset,
127124
this._advance = x;
128125
}
129126

130-
void layoutEmoji(TextStyle style, Font font) {
131-
float x = this._advance;
132-
float letterSpace = style.letterSpacing;
133-
float letterSpaceHalfLeft = letterSpace * 0.5f;
134-
float letterSpaceHalfRight = letterSpace - letterSpaceHalfLeft;
135-
136-
x += letterSpaceHalfLeft;
137-
this._advances[0] += letterSpaceHalfLeft;
138-
139-
var metrics = FontMetrics.fromFont(font, style.UnityFontSize);
140-
141-
var minX = x;
142-
var maxX = metrics.descent - metrics.ascent + x;
143-
var minY = metrics.ascent;
144-
var maxY = metrics.descent;
145-
146-
if (this._bounds.width <= 0 || this._bounds.height <= 0) {
147-
this._bounds = UnityEngine.Rect.MinMaxRect(
148-
minX, minY, maxX, maxY);
149-
} else {
150-
if (minX < this._bounds.x) {
151-
this._bounds.x = minX;
152-
}
153-
if (minY < this._bounds.y) {
154-
this._bounds.y = minY;
155-
}
156-
if (maxX > this._bounds.xMax) {
157-
this._bounds.xMax = maxX;
158-
}
159-
if (maxY > this._bounds.yMax) {
160-
this._bounds.yMax = maxY;
127+
void layoutEmoji(TextStyle style, Font font, int start, int count) {
128+
for (int i = 0; i < count; i += 2) {
129+
float x = this._advance;
130+
float letterSpace = style.letterSpacing;
131+
float letterSpaceHalfLeft = letterSpace * 0.5f;
132+
float letterSpaceHalfRight = letterSpace - letterSpaceHalfLeft;
133+
134+
x += letterSpaceHalfLeft;
135+
this._advances[i] += letterSpaceHalfLeft;
136+
137+
var metrics = FontMetrics.fromFont(font, style.UnityFontSize);
138+
139+
var minX = x;
140+
var maxX = metrics.descent - metrics.ascent + x;
141+
var minY = metrics.ascent;
142+
var maxY = metrics.descent;
143+
144+
if (this._bounds.width <= 0 || this._bounds.height <= 0) {
145+
this._bounds = UnityEngine.Rect.MinMaxRect(
146+
minX, minY, maxX, maxY);
147+
} else {
148+
if (minX < this._bounds.x) {
149+
this._bounds.x = minX;
150+
}
151+
if (minY < this._bounds.y) {
152+
this._bounds.y = minY;
153+
}
154+
if (maxX > this._bounds.xMax) {
155+
this._bounds.xMax = maxX;
156+
}
157+
if (maxY > this._bounds.yMax) {
158+
this._bounds.yMax = maxY;
159+
}
161160
}
162-
}
163-
164-
this._positions[0] = x;
165-
float advance = style.fontSize;
166-
x += advance;
167-
168-
this._advances[0] += advance;
169-
this._advances[0] += letterSpaceHalfRight;
170-
x += letterSpaceHalfRight;
171161

172-
this._advances[1] = 0;
173-
this._positions[1] = x;
174-
175-
this._advance = x;
162+
this._positions[i] = x;
163+
float advance = style.fontSize;
164+
x += advance;
165+
166+
this._advances[i] += advance;
167+
this._advances[i] += letterSpaceHalfRight;
168+
x += letterSpaceHalfRight;
169+
170+
this._advances[i+1] = 0;
171+
this._positions[i+1] = x;
172+
173+
this._advance = x;
174+
}
176175
}
177176

178177
public void setTabStops(TabStops tabStops) {

0 commit comments

Comments
 (0)