浏览代码

fix text perf issue

/main
fzhangtj 6 年前
当前提交
040ae059
共有 7 个文件被更改,包括 262 次插入75 次删除
  1. 8
      Assets/UIWidgets/Tests/Widgets.cs
  2. 10
      Assets/UIWidgets/ui/painting/canvas_impl.cs
  3. 73
      Assets/UIWidgets/ui/painting/txt/font_manager.cs
  4. 213
      Assets/UIWidgets/ui/painting/txt/mesh_generator.cs
  5. 2
      Assets/UIWidgets/ui/txt/linebreaker.cs
  6. 26
      Assets/UIWidgets/ui/txt/paragraph.cs
  7. 5
      Assets/UIWidgets/widgets/binding.cs

8
Assets/UIWidgets/Tests/Widgets.cs


}
public static class Icons {
public static readonly IconData notifications = new IconData(0xe7f4, fontFamily: "MaterialIcons");
public static readonly IconData account_circle = new IconData(0xe853, fontFamily: "MaterialIcons");
public static readonly IconData search = new IconData(0xe8b6, fontFamily: "MaterialIcons");
public static readonly IconData keyboard_arrow_down = new IconData(0xe313, fontFamily: "MaterialIcons");
public static readonly IconData notifications = new IconData(0xe7f4, fontFamily: "Material Icons");
public static readonly IconData account_circle = new IconData(0xe853, fontFamily: "Material Icons");
public static readonly IconData search = new IconData(0xe8b6, fontFamily: "Material Icons");
public static readonly IconData keyboard_arrow_down = new IconData(0xe313, fontFamily: "Material Icons");
}
public static class CLColors {

10
Assets/UIWidgets/ui/painting/canvas_impl.cs


public void drawTextBlob(TextBlob textBlob, double x, double y)
{
var mesh = MeshGenrator.generateMesh(textBlob, x, y);
var font = FontManager.instance.getOrCreate(textBlob.style.fontFamily, textBlob.style.UnityFontSize);
var mesh = MeshGenrator.generateMesh(textBlob);
var font = FontManager.instance.getOrCreate(textBlob.style.fontFamily).font;
prepareGL(font.material);
font.material.SetPass(0);
Matrix4x4 cameraMat = Matrix4x4.identity;

Camera.current.worldToCameraMatrix = Matrix4x4.identity;
}
Graphics.DrawMeshNow(mesh, this._transform);
var textBlobOffset = textBlob.positions[textBlob.start];
Graphics.DrawMeshNow(mesh, this._transform * Matrix4x4.Translate(
new Vector3((float) Utils.PixelCorrectRound(x + textBlobOffset.x),
(float) Utils.PixelCorrectRound(y + textBlobOffset.y), 0)));
if (Camera.current != null)
{
Camera.current.worldToCameraMatrix = cameraMat;

73
Assets/UIWidgets/ui/painting/txt/font_manager.cs


namespace UIWidgets.ui
{
public class FontInfo
{
public readonly Font font;
private int _textureVersion;
public FontInfo(Font font)
{
this.font = font;
this._textureVersion = 0;
}
public int textureVersion
{
get { return _textureVersion; }
}
public void onTextureRebuilt()
{
_textureVersion++;
}
}
private List<Font> _fonts = new List<Font>();
private List<FontInfo> _fonts = new List<FontInfo>();
private static readonly int defaultFontSize = 14;
public Font getOrCreate(string[] names, int fontSize)
private FontManager()
{
Font.textureRebuilt += this.onFontTextureRebuilt;
}
public FontInfo getOrCreate(string[] names)
_fonts = _fonts.FindAll((font) => font != null); // filter out destoryed fonts
var founded = _fonts.Find((font) =>
(
font.fontSize == fontSize &&
(names == font.fontNames || (names != null && names.SequenceEqual(font.fontNames)))));
_fonts = _fonts.FindAll((info) => info.font != null); // filter out destoryed fonts
var founded = _fonts.Find((info) =>
( (names == info.font.fontNames || (names != null &&
names.SequenceEqual(info.font.fontNames)))));
if (names.SequenceEqual(new string[] {"MaterialIcons"})) {
if (names.SequenceEqual(new string[] {"Material Icons"}))
{
_fonts.Add(font);
return font;
var fontInfo = new FontInfo(font);
_fonts.Add(fontInfo);
return fontInfo;
var newFont = Font.CreateDynamicFontFromOSFont(names, fontSize);
var newFont = new FontInfo(Font.CreateDynamicFontFromOSFont(names, defaultFontSize));
public Font getOrCreate(string name, int fontSize)
public FontInfo getOrCreate(string name)
return getOrCreate(new []{name}, fontSize);
return getOrCreate(new[] {name});
}
private void onFontTextureRebuilt(Font font)
{
var id = font.GetInstanceID();
var entry = _fonts.Find((f) => f.font != null && f.font.GetInstanceID() == id);
if (entry != null)
{
entry.onTextureRebuilt();
}
}
}

213
Assets/UIWidgets/ui/painting/txt/mesh_generator.cs


using UIWidgets.ui.txt;
using System;
using System.Collections.Generic;
using System.Linq;
using UIWidgets.ui.txt;
public class MeshKey : IEquatable<MeshKey>
{
public readonly string text;
public readonly int fontId;
public readonly int textureVersion;
public readonly int fontSize;
public readonly UnityEngine.FontStyle fontStyle;
public readonly float pixelPerPoint;
public readonly UnityEngine.Color color;
public MeshKey(string text, int fontId, int textureVersion, int fontSize,
UnityEngine.FontStyle fontStyle, float pixelPerPoint, UnityEngine.Color color)
{
this.text = text;
this.fontId = fontId;
this.textureVersion = textureVersion;
this.fontSize = fontSize;
this.fontStyle = fontStyle;
this.pixelPerPoint = pixelPerPoint;
this.color = color;
}
public bool Equals(MeshKey other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return string.Equals(text, other.text) && fontId == other.fontId &&
textureVersion == other.textureVersion && fontSize == other.fontSize &&
fontStyle == other.fontStyle && pixelPerPoint.Equals(other.pixelPerPoint) &&
color.Equals(other.color);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((MeshKey) obj);
}
public override int GetHashCode()
{
unchecked
{
var hashCode = (text != null ? text.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ fontId;
hashCode = (hashCode * 397) ^ textureVersion;
hashCode = (hashCode * 397) ^ fontSize;
hashCode = (hashCode * 397) ^ (int) fontStyle;
hashCode = (hashCode * 397) ^ pixelPerPoint.GetHashCode();
hashCode = (hashCode * 397) ^ color.GetHashCode();
return hashCode;
}
}
public static bool operator ==(MeshKey left, MeshKey right)
{
return Equals(left, right);
}
public static bool operator !=(MeshKey left, MeshKey right)
{
return !Equals(left, right);
}
public override string ToString()
{
return string.Format(
"Text: {0}, FontId: {1}, TextureVersion: {2}, FontSize: {3}, FontStyle: {4}, PixelPerPoint: {5}, Color: {6}",
text, fontId, textureVersion, fontSize, fontStyle, pixelPerPoint, color);
}
}
public class MeshInfo
{
public readonly Mesh mesh;
public readonly MeshKey key;
public long _timeToLive;
public MeshInfo(MeshKey key, Mesh mesh, int timeToLive = 5)
{
this.mesh = mesh;
this.key = key;
this.touch(timeToLive);
}
public long timeToLive
{
get { return _timeToLive; }
}
public void touch(long timeTolive = 5)
{
this._timeToLive = timeTolive + MeshGenrator.frameCount;
}
}
public static Mesh generateMesh(TextBlob textBlob, double x, double y)
private static Dictionary<MeshKey, MeshInfo> _meshes = new Dictionary<MeshKey, MeshInfo>();
private static long _frameCount = 0;
public static long frameCount
{
get { return _frameCount; }
}
public static long MeshCount
{
get { return _meshes.Count; }
}
public static void tickNextFrame()
{
_frameCount++;
var keysToRemove = _meshes.Values.Where(info => info.timeToLive < _frameCount).Select(info => info.key).ToList();
foreach (var key in keysToRemove)
{
_meshes.Remove(key);
}
}
public static Mesh generateMesh(TextBlob textBlob)
var font = FontManager.instance.getOrCreate(style.fontFamily, style.UnityFontSize);
var fontInfo = FontManager.instance.getOrCreate(style.fontFamily);
var font = fontInfo.font;
var vertices = new Vector3[length * 4];
var triangles = new int[length * 6];
var uv = new Vector2[length * 4];
var fontSizeToLoad = (int)scale * style.UnityFontSize;
var offset = new Vector3((float)Utils.PixelCorrectRound(x), (float)Utils.PixelCorrectRound(y), 0);
font.RequestCharactersInTexture(textBlob.text.Substring(textBlob.start, textBlob.end - textBlob.start),
var fontSizeToLoad = (int) scale * style.UnityFontSize;
var subText = textBlob.text.Substring(textBlob.start, textBlob.end - textBlob.start);
font.RequestCharactersInTexture(subText,
MeshInfo meshInfo;
var key = new MeshKey(subText, font.GetInstanceID(),
fontInfo.textureVersion,
style.UnityFontSize, style.UnityFontStyle, scale, style.UnityColor);
Mesh mesh = null;
_meshes.TryGetValue(key, out meshInfo);
if (meshInfo != null)
{
mesh = meshInfo.mesh;
meshInfo.touch();
}
if (mesh != null)
{
return mesh;
}
var vertices = new Vector3[length * 4];
var triangles = new int[length * 6];
var uv = new Vector2[length * 4];
mesh = new Mesh();
_meshes[key] = new MeshInfo(key, mesh);
var position = textBlob.positions[charIndex + textBlob.start];
CharacterInfo charInfo = new CharacterInfo();
if (Paragraph.isWordSpace(ch) || Paragraph.isLineEndSpace(ch) || ch== '\t')
// first char as origin for mesh position
var position = textBlob.positions[charIndex + textBlob.start] - textBlob.positions[textBlob.start];
if (Paragraph.isWordSpace(ch) || Paragraph.isLineEndSpace(ch) || ch == '\t')
vertices[4 * charIndex + 2] = vertices[4 * charIndex + 3] = offset;
vertices[4 * charIndex + 2] = vertices[4 * charIndex + 3] = Vector3.zero;
uv[4 * charIndex + 0] = Vector2.zero;
uv[4 * charIndex + 1] = Vector2.zero;
uv[4 * charIndex + 2] = Vector2.zero;

{
CharacterInfo charInfo;
vertices[4 * charIndex + 0] = offset + new Vector3((float)(position.x + minX),
(float)(position.y - maxY), 0);
vertices[4 * charIndex + 1] = offset + new Vector3((float)(position.x + maxX),
(float)(position.y - maxY), 0);
vertices[4 * charIndex + 2] = offset + new Vector3(
(float)(position.x + maxX), (float)(position.y - minY), 0);
vertices[4 * charIndex + 3] = offset + new Vector3(
(float)(position.x + minX), (float)(position.y - minY), 0);
vertices[4 * charIndex + 0] = new Vector3((float) (position.x + minX),
(float) (position.y - maxY), 0);
vertices[4 * charIndex + 1] = new Vector3((float) (position.x + maxX),
(float) (position.y - maxY), 0);
vertices[4 * charIndex + 2] = new Vector3(
(float) (position.x + maxX), (float) (position.y - minY), 0);
vertices[4 * charIndex + 3] = new Vector3(
(float) (position.x + minX), (float) (position.y - minY), 0);
}
}
triangles[6 * charIndex + 0] = 4 * charIndex + 0;
triangles[6 * charIndex + 1] = 4 * charIndex + 1;
triangles[6 * charIndex + 2] = 4 * charIndex + 2;

triangles[6 * charIndex + 5] = 4 * charIndex + 3;
}
var mesh = new Mesh()
{
vertices = vertices,
triangles = triangles,
uv = uv
};
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.uv = uv;
return mesh;
}
}

2
Assets/UIWidgets/ui/txt/linebreaker.cs


{
runIterator.nextTo(charIndex);
var run = runIterator.run;
var font = FontManager.instance.getOrCreate(run.style.fontFamily, run.style.UnityFontSize);
var font = FontManager.instance.getOrCreate(run.style.fontFamily).font;
var style = run.style;
var charInfo = new CharacterInfo();

26
Assets/UIWidgets/ui/txt/paragraph.cs


this.fxHeight = fxHeight;
}
public static FontMetrics fromFont(Font font, double? height)
public static FontMetrics fromFont(Font font, int fontSize, double? height)
var ascent = font.ascent * (height??1.0);
var descent = (font.lineHeight - font.ascent) * (height??1.0);
var ascent = font.ascent * (height??1.0) * fontSize / font.fontSize;
var descent = (font.lineHeight - font.ascent) * (height??1.0) * fontSize / font.fontSize;
font.RequestCharactersInTexture("x");
font.RequestCharactersInTexture("x", fontSize);
if (font.GetCharacterInfo('x', out charInfo))
if (font.GetCharacterInfo('x', out charInfo, fontSize))
{
fxHeight = charInfo.glyphHeight;
}

var run = _runs.getRun(i);
if (run.start < run.end)
{
var font = FontManager.instance.getOrCreate(run.style.fontFamily, run.style.UnityFontSize);
font.RequestCharactersInTexture(_text.Substring(run.start, run.end - run.start), 0,
var font = FontManager.instance.getOrCreate(run.style.fontFamily).font;
font.RequestCharactersInTexture(_text.Substring(run.start, run.end - run.start), run.style.UnityFontSize,
run.style.UnityFontStyle);
}
}

var run = runIndex < _runs.size ? _runs.getRun(runIndex) : null;
if (run != null && run.start < run.end && run.start < line.end && run.end > line.start)
{
var font = FontManager.instance.getOrCreate(run.style.fontFamily, run.style.UnityFontSize);
var styleHeight = (double) run.style.UnityFontSize / font.fontSize;
run.style.height = styleHeight;
var metrics = FontMetrics.fromFont(font, run.style.height);
var ascent = font.ascent * (run.style.height);
var descent = (font.lineHeight - font.ascent) * (run.style.height);
var font = FontManager.instance.getOrCreate(run.style.fontFamily).font;
var metrics = FontMetrics.fromFont(font, run.style.UnityFontSize, run.style.height);
if (metrics.ascent > maxAscent)
{
maxAscent = metrics.ascent;

_characterPositions[start].x;
if (end > start)
{
var bounds = Rect.fromLTWH(0, -ascent,
var bounds = Rect.fromLTWH(0, -metrics.ascent,
descent);
metrics.descent);
linePaintRecords.Add(new PaintRecord(run.style, new Offset(_characterPositions[start].x, yOffset)
, new TextBlob(

5
Assets/UIWidgets/widgets/binding.cs


using UIWidgets.foundation;
using UIWidgets.rendering;
using UIWidgets.ui;
using UIWidgets.ui.painting.txt;
namespace UIWidgets.widgets {
public interface WidgetsBindingObserver {

public WidgetsBinding() {
this.buildOwner.onBuildScheduled = this._handleBuildScheduled;
Window.instance.onLocaleChanged += this.handleLocaleChanged;
this.addPersistentFrameCallback((duration) =>
{
MeshGenrator.tickNextFrame();
});
}
public BuildOwner buildOwner {

正在加载...
取消
保存