浏览代码

Render continuous emojis in one draw call.

/main
Yuncong Zhang 5 年前
当前提交
6c5cc807
共有 3 个文件被更改,包括 90 次插入75 次删除
  1. 54
      Runtime/ui/painting/txt/mesh_generator.cs
  2. 22
      Runtime/ui/txt/emoji.cs
  3. 89
      Runtime/ui/txt/layout.cs

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


var font = fontInfo.font;
if (char.IsHighSurrogate(text[this.textBlob.textOffset])) {
D.assert(this.textBlob.textSize == 2);
char a = text[this.textBlob.textOffset], b = text[this.textBlob.textOffset+1];
D.assert(char.IsLowSurrogate(b));
var pos = this.textBlob.positions[0];
D.assert(this.textBlob.textSize % 2 == 0);
var vert = new List<Vector3>();
var tri = new List<int>();
var uvCoord = new List<Vector2>();
var vert = new List<Vector3> {
new Vector3(pos.x + minX, pos.y + minY, 0),
new Vector3(pos.x + maxX, pos.y + minY, 0),
new Vector3(pos.x + maxX, pos.y + maxY, 0),
new Vector3(pos.x + minX, pos.y + maxY, 0),
};
var tri = new List<int> {
0, 1, 2, 0, 2, 3,
};
var code = char.ConvertToUtf32(a, b);
var uvRect = EmojiUtils.getUVRect(code);
var uvCoord = new List<Vector2> {
uvRect.bottomLeft.toVector(),
uvRect.bottomRight.toVector(),
uvRect.topRight.toVector(),
uvRect.topLeft.toVector(),
};
for (int i = 0; i < this.textBlob.textSize; i += 2) {
char a = text[this.textBlob.textOffset+i], b = text[this.textBlob.textOffset+i+1];
D.assert(char.IsLowSurrogate(b));
var pos = this.textBlob.positions[i];
vert.Add(new Vector3(pos.x + minX, pos.y + minY, 0));
vert.Add(new Vector3(pos.x + maxX, pos.y + minY, 0));
vert.Add(new Vector3(pos.x + maxX, pos.y + maxY, 0));
vert.Add(new Vector3(pos.x + minX, pos.y + maxY, 0));
tri.Add(i * 2);
tri.Add(i * 2 + 1);
tri.Add(i * 2 + 2);
tri.Add(i * 2);
tri.Add(i * 2 + 2);
tri.Add(i * 2 + 3);
var code = char.ConvertToUtf32(a, b);
var uvRect = EmojiUtils.getUVRect(code);
uvCoord.Add(uvRect.bottomLeft.toVector());
uvCoord.Add(uvRect.bottomRight.toVector());
uvCoord.Add(uvRect.topRight.toVector());
uvCoord.Add(uvRect.topLeft.toVector());
}
MeshMesh meshMesh = new MeshMesh(null, vert, tri, uvCoord);
_meshes[key] = new MeshInfo(key, meshMesh, 0);

22
Runtime/ui/txt/emoji.cs


public static List<string> splitBySurrogatePair(string text) {
int start = 0;
bool? currentSurrogate = null;
if (i > start) {
list.Add(text.Substring(start, i - start));
if (currentSurrogate != true) {
if (i > start) {
list.Add(text.Substring(start, i - start));
start = i;
}
start = i + 2;
list.Add(text.Substring(i, 2));
currentSurrogate = true;
}
else {
if (currentSurrogate != false) {
if (i > start) {
list.Add(text.Substring(start, i - start));
start = i;
}
}
currentSurrogate = false;
}
}

89
Runtime/ui/txt/layout.cs


Font font = FontManager.instance.getOrCreate(style.fontFamily, style.fontWeight, style.fontStyle).font;
if (char.IsHighSurrogate(buff.text[buff.offset + start])) {
D.assert(count == 2);
D.assert(char.IsLowSurrogate(buff.text[buff.offset + start+1]));
this.layoutEmoji(style, font);
this.layoutEmoji(style, font, start, count);
}
else {
font.RequestCharactersInTextureSafe(buff.text, style.UnityFontSize, style.UnityFontStyle);

this._advance = x;
}
void layoutEmoji(TextStyle style, Font font) {
float x = this._advance;
float letterSpace = style.letterSpacing;
float letterSpaceHalfLeft = letterSpace * 0.5f;
float letterSpaceHalfRight = letterSpace - letterSpaceHalfLeft;
x += letterSpaceHalfLeft;
this._advances[0] += letterSpaceHalfLeft;
var metrics = FontMetrics.fromFont(font, style.UnityFontSize);
void layoutEmoji(TextStyle style, Font font, int start, int count) {
for (int i = 0; i < count; i += 2) {
float x = this._advance;
float letterSpace = style.letterSpacing;
float letterSpaceHalfLeft = letterSpace * 0.5f;
float letterSpaceHalfRight = letterSpace - letterSpaceHalfLeft;
x += letterSpaceHalfLeft;
this._advances[i] += letterSpaceHalfLeft;
var metrics = FontMetrics.fromFont(font, style.UnityFontSize);
var minX = x;
var maxX = metrics.descent - metrics.ascent + x;
var minY = metrics.ascent;
var maxY = metrics.descent;
var minX = x;
var maxX = metrics.descent - metrics.ascent + x;
var minY = metrics.ascent;
var maxY = metrics.descent;
if (this._bounds.width <= 0 || this._bounds.height <= 0) {
this._bounds = UnityEngine.Rect.MinMaxRect(
minX, minY, maxX, maxY);
} else {
if (minX < this._bounds.x) {
this._bounds.x = minX;
}
if (minY < this._bounds.y) {
this._bounds.y = minY;
}
if (maxX > this._bounds.xMax) {
this._bounds.xMax = maxX;
}
if (maxY > this._bounds.yMax) {
this._bounds.yMax = maxY;
if (this._bounds.width <= 0 || this._bounds.height <= 0) {
this._bounds = UnityEngine.Rect.MinMaxRect(
minX, minY, maxX, maxY);
} else {
if (minX < this._bounds.x) {
this._bounds.x = minX;
}
if (minY < this._bounds.y) {
this._bounds.y = minY;
}
if (maxX > this._bounds.xMax) {
this._bounds.xMax = maxX;
}
if (maxY > this._bounds.yMax) {
this._bounds.yMax = maxY;
}
}
this._positions[0] = x;
float advance = style.fontSize;
x += advance;
this._advances[0] += advance;
this._advances[0] += letterSpaceHalfRight;
x += letterSpaceHalfRight;
this._positions[i] = x;
float advance = style.fontSize;
x += advance;
this._advances[i] += advance;
this._advances[i] += letterSpaceHalfRight;
x += letterSpaceHalfRight;
this._advances[1] = 0;
this._positions[1] = x;
this._advance = x;
this._advances[i+1] = 0;
this._positions[i+1] = x;
this._advance = x;
}
}
public void setTabStops(TabStops tabStops) {

正在加载...
取消
保存