浏览代码

update

/main
fzhangtj 6 年前
当前提交
d5a10357
共有 31 个文件被更改,包括 2253 次插入1 次删除
  1. 5
      Assets/UIWidgets/Tests/Menu.cs
  2. 11
      Assets/UIWidgets/painting/basic_types.cs
  3. 2
      Assets/UIWidgets/rendering/viewpoint.cs
  4. 1
      Assets/UIWidgets/ui/painting/canvas.cs
  5. 4
      Assets/UIWidgets/ui/painting/draw_cmd.cs
  6. 394
      Assets/UIWidgets/ui/text.cs
  7. 103
      Assets/UIWidgets/Tests/Text.cs
  8. 3
      Assets/UIWidgets/Tests/Text.cs.meta
  9. 118
      Assets/UIWidgets/editor/TextMesh.cs
  10. 3
      Assets/UIWidgets/editor/TextMesh.cs.meta
  11. 3
      Assets/UIWidgets/math.meta
  12. 288
      Assets/UIWidgets/painting/text_painter.cs
  13. 3
      Assets/UIWidgets/painting/text_painter.cs.meta
  14. 246
      Assets/UIWidgets/painting/text_span.cs
  15. 84
      Assets/UIWidgets/painting/text_style.cs
  16. 3
      Assets/UIWidgets/painting/text_style.cs.meta
  17. 235
      Assets/UIWidgets/rendering/paragraph.cs
  18. 3
      Assets/UIWidgets/rendering/paragraph.cs.meta
  19. 3
      Assets/UIWidgets/ui/txt.meta
  20. 14
      Assets/UIWidgets/math/math.cs
  21. 3
      Assets/UIWidgets/math/math.cs.meta
  22. 177
      Assets/UIWidgets/ui/txt/linebreaker.cs
  23. 3
      Assets/UIWidgets/ui/txt/linebreaker.cs.meta
  24. 348
      Assets/UIWidgets/ui/txt/paragraph.cs
  25. 3
      Assets/UIWidgets/ui/txt/paragraph.cs.meta
  26. 75
      Assets/UIWidgets/ui/txt/paragraph_builder.cs
  27. 3
      Assets/UIWidgets/ui/txt/paragraph_builder.cs.meta
  28. 113
      Assets/UIWidgets/ui/txt/styled_runs.cs
  29. 3
      Assets/UIWidgets/ui/txt/styled_runs.cs.meta

5
Assets/UIWidgets/Tests/Menu.cs


public static void renderBoxes() {
EditorWindow.GetWindow(typeof(RenderBoxes));
}
[MenuItem("UIWidgetsTests/Text")]
public static void renderText() {
EditorWindow.GetWindow(typeof(Text));
}
}
}

11
Assets/UIWidgets/painting/basic_types.cs


throw new Exception("unknown axisDirection");
}
}
/// The values in this enum are ordered such that they are in increasing order
/// of cost. A value with index N implies all the values with index less than N.
/// For example, [layout] (index 3) implies [paint] (2).
public enum RenderComparison
{
identical,
metadata,
paint,
layout,
}
}

2
Assets/UIWidgets/rendering/viewpoint.cs


double cacheExtent = RenderAbstractViewportUtils.defaultCacheExtent,
AxisDirection axisDirection = AxisDirection.down) : base(crossAxisDirection, offset, cacheExtent,
axisDirection) {
Font x = new Font();
// x.characterInfo
}
}
}

1
Assets/UIWidgets/ui/painting/canvas.cs


void clipRect(Rect rect);
void clipRRect(RRect rrect);
}
public class RecorderCanvas : Canvas {

4
Assets/UIWidgets/ui/painting/draw_cmd.cs


public class DrawClipRRect : DrawCmd {
public RRect rrect;
}
public class DrawMesh : DrawCmd {
public Mesh mesh;
}
}

394
Assets/UIWidgets/ui/text.cs


namespace UIWidgets.ui {
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
namespace UIWidgets.ui {
public enum FontStyle {
/// Use the upright glyphs
normal,
/// Use glyphs designed for slanting
italic,
}
public enum TextAlign {
/// Align the text on the left edge of the container.
left,
/// Align the text on the right edge of the container.
right,
/// Align the text in the center of the container.
center,
/// Stretch lines of text that end with a soft line break to fill the width of
/// the container.
///
/// Lines that end with hard line breaks are aligned towards the [start] edge.
justify,
}
public class ParagraphConstraints: IEquatable<ParagraphConstraints>
{
public readonly double width;
public ParagraphConstraints(double width)
{
this.width = width;
}
public bool Equals(ParagraphConstraints other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return width.Equals(other.width);
}
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((ParagraphConstraints) obj);
}
public override int GetHashCode()
{
return width.GetHashCode();
}
public override string ToString()
{
return string.Format("Width: {0}", width);
}
}
public class TextStyle:IEquatable<TextStyle>
{
public static readonly string defaultFontFamily = "Helvetica";
public static readonly double defaultFontSize = 14.0;
public static readonly FontWeight defaultFontWeight = FontWeight.w400;
public static readonly FontStyle defaultFontStyle = FontStyle.normal;
public Color color;
public double? fontSize;
public FontWeight? fontWeight;
public FontStyle? fontStyle;
public double? letterSpacing;
public double? wordSpacing;
public TextBaseline? textBaseline;
public double? height;
public TextDecoration decoration;
public string fontFamily;
public FontStyle safeFontStyle
{
get { return fontStyle ?? defaultFontStyle; }
}
public string safeFontFamily
{
get { return fontFamily ?? defaultFontFamily; }
}
public double safeFontSize
{
get { return fontSize ?? defaultFontSize; }
}
public FontWeight safeFontWeight
{
get { return fontWeight ?? defaultFontWeight; }
}
public UnityEngine.FontStyle UnityFontStyle
{
get
{
if (safeFontStyle == FontStyle.italic)
{
if (safeFontWeight == FontWeight.w700)
{
return UnityEngine.FontStyle.BoldAndItalic;
}
else
{
return UnityEngine.FontStyle.Italic;
}
} else if (safeFontWeight == FontWeight.w700)
{
return UnityEngine.FontStyle.Bold;
}
return UnityEngine.FontStyle.Normal;
}
}
public int UnityFontSize
{
get { return (int) safeFontSize; }
}
public TextStyle merge(TextStyle style)
{
var ret = new TextStyle();
ret.color = style.color??color;
ret.fontSize = style.fontSize??fontSize;
ret.fontWeight = style.fontWeight??fontWeight;
ret.fontStyle = style.fontStyle??fontStyle;
ret.letterSpacing = style.letterSpacing??letterSpacing;
ret.textBaseline = style.textBaseline??textBaseline;
ret.height = style.height??height;
ret.decoration = style.decoration??decoration;
ret.fontFamily = style.fontFamily??fontFamily;
return ret;
}
public bool Equals(TextStyle other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return color == other.color && fontSize == other.fontSize && fontWeight == other.fontWeight &&
fontStyle == other.fontStyle && letterSpacing == other.letterSpacing &&
wordSpacing == other.wordSpacing && textBaseline == other.textBaseline &&
height == other.height && decoration == other.decoration && fontFamily == other.fontFamily;
}
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((TextStyle) obj);
}
public override int GetHashCode()
{
unchecked
{
var hashCode = (color != null ? color.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ fontSize.GetHashCode();
hashCode = (hashCode * 397) ^ fontWeight.GetHashCode();
hashCode = (hashCode * 397) ^ fontStyle.GetHashCode();
hashCode = (hashCode * 397) ^ letterSpacing.GetHashCode();
hashCode = (hashCode * 397) ^ wordSpacing.GetHashCode();
hashCode = (hashCode * 397) ^ textBaseline.GetHashCode();
hashCode = (hashCode * 397) ^ height.GetHashCode();
hashCode = (hashCode * 397) ^ (decoration != null ? decoration.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (fontFamily != null ? fontFamily.GetHashCode() : 0);
return hashCode;
}
}
public static bool operator ==(TextStyle left, TextStyle right)
{
return Equals(left, right);
}
public static bool operator !=(TextStyle left, TextStyle right)
{
return !Equals(left, right);
}
public TextStyle(Color color = null, double? fontSize = default(double?), FontWeight? fontWeight = default(FontWeight?), FontStyle? fontStyle = default(FontStyle?), double? letterSpacing = default(double?), double? wordSpacing = default(double?), TextBaseline? textBaseline = default(TextBaseline?), double? height = default(double?), TextDecoration decoration = null, string fontFamily = null)
{
this.color = color;
this.fontSize = fontSize;
this.fontWeight = fontWeight;
this.fontStyle = fontStyle;
this.letterSpacing = letterSpacing;
this.wordSpacing = wordSpacing;
this.textBaseline = textBaseline;
this.height = height;
this.decoration = decoration;
this.fontFamily = fontFamily;
}
}
public class ParagraphStyle: IEquatable<ParagraphStyle>
{
public ParagraphStyle(TextAlign? textAlign = null,
TextDirection? textDirection = null,
FontWeight? fontWeight = null,
FontStyle? fontStyle = null,
int? maxLines = null,
double? fontSize = null,
string fontFamily = null,
double? lineHeight = null, // todo
string ellipsis = null)
{
this.textAlign = textAlign;
this.textDirection = textDirection;
this.fontWeight = fontWeight;
this.fontStyle = fontStyle;
this.maxLines = maxLines;
this.fontSize = fontSize;
this.fontFamily = fontFamily;
this.lineHeight = lineHeight;
this.ellipsis = ellipsis;
}
public bool Equals(ParagraphStyle other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return textAlign == other.textAlign && textDirection == other.textDirection && fontWeight == other.fontWeight && fontStyle == other.fontStyle && maxLines == other.maxLines && fontSize.Equals(other.fontSize) && string.Equals(fontFamily, other.fontFamily) && lineHeight.Equals(other.lineHeight) && string.Equals(ellipsis, other.ellipsis);
}
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((ParagraphStyle) obj);
}
public static bool operator ==(ParagraphStyle a, ParagraphStyle b) {
return Equals(a, b);
}
public static bool operator !=(ParagraphStyle a, ParagraphStyle b) {
return !(a == b);
}
public override int GetHashCode()
{
unchecked
{
var hashCode = textAlign.GetHashCode();
hashCode = (hashCode * 397) ^ textDirection.GetHashCode();
hashCode = (hashCode * 397) ^ fontWeight.GetHashCode();
hashCode = (hashCode * 397) ^ fontStyle.GetHashCode();
hashCode = (hashCode * 397) ^ maxLines.GetHashCode();
hashCode = (hashCode * 397) ^ fontSize.GetHashCode();
hashCode = (hashCode * 397) ^ (fontFamily != null ? fontFamily.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ lineHeight.GetHashCode();
hashCode = (hashCode * 397) ^ (ellipsis != null ? ellipsis.GetHashCode() : 0);
return hashCode;
}
}
public TextStyle getTextStyle()
{
return new TextStyle(
fontWeight: fontWeight,
fontStyle: fontStyle,
fontFamily: fontFamily,
fontSize: fontSize,
height: lineHeight
);
}
public readonly TextAlign? textAlign;
public readonly TextDirection? textDirection;
public readonly FontWeight? fontWeight;
public readonly FontStyle? fontStyle;
public readonly int? maxLines;
public readonly double? fontSize;
public readonly string fontFamily;
public readonly double? lineHeight;
public readonly string ellipsis;
}
public class TextDecoration: IEquatable<TextDecoration>
{
public bool Equals(TextDecoration other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return mask == other.mask;
}
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((TextDecoration) obj);
}
public override int GetHashCode()
{
return mask;
}
public static bool operator ==(TextDecoration a, TextDecoration b) {
return Equals(a, b);
}
public static bool operator !=(TextDecoration a, TextDecoration b) {
return !(a == b);
}
public static readonly TextDecoration none = new TextDecoration(0);
public static readonly TextDecoration underline = new TextDecoration(1);
public static readonly TextDecoration overline = new TextDecoration(2);
public static readonly TextDecoration lineThrough = new TextDecoration(4);
public readonly int mask;
public TextDecoration(int mask)
{
this.mask = mask;
}
bool contains(TextDecoration other) {
return (mask | other.mask) == mask;
}
}
}
public enum TextAffinity {
upstream,
downstream,
}
public enum FontWeight
{
w400, // normal
w700, // bold
}
public class TextPosition
{
public readonly int offset;
public readonly TextAffinity affinity;
public TextPosition(int offset, TextAffinity affinity = TextAffinity.downstream)
{
this.offset = offset;
this.affinity = affinity;
}
public override string ToString()
{
return string.Format("Offset: {0}, Affinity: {1}", offset, affinity);
}
protected bool Equals(TextPosition other)
{
return offset == other.offset && affinity == other.affinity;
}
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((TextPosition) obj);
}
public override int GetHashCode()
{
unchecked
{
return (offset * 397) ^ (int) affinity;
}
}
}
}

103
Assets/UIWidgets/Tests/Text.cs


using System;
using System.Collections.Generic;
using System.Linq;
using UIWidgets.editor;
using UIWidgets.painting;
using UIWidgets.rendering;
using UIWidgets.ui;
using UnityEditor;
using UnityEngine;
using Color = UIWidgets.ui.Color;
using FontStyle = UIWidgets.ui.FontStyle;
using Rect = UIWidgets.ui.Rect;
namespace UIWidgets.Tests
{
public class Text : EditorWindow
{
private readonly Func<RenderBox>[] _options;
private readonly string[] _optionStrings;
private int _selected;
Text() {
this._options = new Func<RenderBox>[] {
this.text,
};
this._optionStrings = this._options.Select(x => x.Method.Name).ToArray();
this._selected = 0;
this.titleContent = new GUIContent("RenderBoxes");
}
private WindowAdapter windowAdapter;
private RendererBindings rendererBindings;
[NonSerialized] private bool hasInvoked = false;
void OnGUI() {
var selected = EditorGUILayout.Popup("test case", this._selected, this._optionStrings);
if (selected != this._selected || !this.hasInvoked) {
this._selected = selected;
this.hasInvoked = true;
var renderBox = this._options[this._selected]();
this.rendererBindings.setRoot(renderBox);
}
if (this.windowAdapter != null) {
this.windowAdapter.OnGUI();
}
}
void Update() {
if (this.windowAdapter != null) {
this.windowAdapter.Update();
}
}
private void OnEnable() {
this.windowAdapter = new WindowAdapter(this);
this.rendererBindings = new RendererBindings(this.windowAdapter);
}
void OnDestroy() {
this.windowAdapter = null;
this.rendererBindings = null;
}
RenderBox none() {
return null;
}
RenderBox text()
{
/*
*bool inherit, Color color, double? fontSize, FontWeight fontWeight,
FontStyle fontStyle, double letterSpacing, double wordSpacing,
TextBaseline textBaseline, double height, TextDecoration decoration
*
*/
var style1 = new painting.TextStyle(true, Color.fromARGB(1, 2, 2, 2), null, FontWeight.w400, FontStyle.normal, 1,
1, TextBaseline.alphabetic, 1, TextDecoration.none);
var style2 = new painting.TextStyle(true, Color.fromARGB(1, 2, 2, 2), null, FontWeight.w400, FontStyle.normal, 1,
1, TextBaseline.alphabetic, 1, TextDecoration.none);
return new RenderConstrainedOverflowBox(
minWidth: 100,
maxWidth: 100,
minHeight: 100,
maxHeight: 100,
child: new RenderParagraph(new TextSpan(style1, "",
new List<TextSpan>()
{
new TextSpan(null, "Hello sda fdf asdf asd fadsfdfs fdsffsdf d sdfsfsf sd fsfsdf", null),
new TextSpan(null, "TextBaseline textBaseline, double height, TextDecoration decoration", null),
new TextSpan(style2, " Unity Widgets", null),
new TextSpan(null, " Text", null)
}))
);
}
}
}

3
Assets/UIWidgets/Tests/Text.cs.meta


fileFormatVersion: 2
guid: f4121086094d45de9e29781269270102
timeCreated: 1535424100

118
Assets/UIWidgets/editor/TextMesh.cs


using UnityEditor;
using UnityEngine;
namespace UIWidgets.editor
{
public class TextMeshWindow : EditorWindow
{
Font font;
string str = "Hello World";
Mesh mesh;
// Add menu named "My Window" to the Window menu
[MenuItem("TextMeshWindow/TextMeshWindow")]
static void Init()
{
// Get existing open window or if none, make a new one:
TextMeshWindow window = (TextMeshWindow)EditorWindow.GetWindow(typeof(TextMeshWindow));
window.Show();
}
void OnFontTextureRebuilt(Font changedFont)
{
if (changedFont != font)
return;
TextGenerator t = new TextGenerator();
RebuildMesh();
}
void RebuildMesh()
{
// Generate a mesh for the characters we want to print.
var vertices = new Vector3[str.Length * 4];
var triangles = new int[str.Length * 6];
var uv = new Vector2[str.Length * 4];
Vector3 pos = Vector3.zero;
for (int i = 0; i < str.Length; i++)
{
// Get character rendering information from the font
CharacterInfo ch;
font.GetCharacterInfo(str[i], out ch);
vertices[4 * i + 0] = pos + new Vector3(ch.minX, -ch.maxY + 100, 0);
vertices[4 * i + 1] = pos + new Vector3(ch.maxX, -ch.maxY + 100, 0);
vertices[4 * i + 2] = pos + new Vector3(ch.maxX, -ch.minY + 100, 0);
vertices[4 * i + 3] = pos + new Vector3(ch.minX, -ch.minY + 100, 0);
uv[4 * i + 0] = ch.uvTopLeft;
uv[4 * i + 1] = ch.uvTopRight;
uv[4 * i + 2] = ch.uvBottomRight;
uv[4 * i + 3] = ch.uvBottomLeft;
triangles[6 * i + 0] = 4 * i + 0;
triangles[6 * i + 1] = 4 * i + 1;
triangles[6 * i + 2] = 4 * i + 2;
triangles[6 * i + 3] = 4 * i + 0;
triangles[6 * i + 4] = 4 * i + 2;
triangles[6 * i + 5] = 4 * i + 3;
// Advance character position
pos += new Vector3(ch.advance, 0, 0);
}
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.uv = uv;
}
private void OnEnable()
{
font = Font.CreateDynamicFontFromOSFont("Helvetica", 16);
// Set the rebuild callback so that the mesh is regenerated on font changes.
Font.textureRebuilt += OnFontTextureRebuilt;
// Request characters.
font.RequestCharactersInTexture(str);
// Set up mesh.
mesh = new Mesh();
// Generate font mesh.
RebuildMesh();
}
void OnGUI()
{
if (Event.current.type == EventType.Repaint)
{
font.RequestCharactersInTexture(str);
Material mat = font.material;
mat.SetPass(0);
Graphics.DrawMeshNow(mesh, Matrix4x4.identity);
// Graphics.DrawMesh(mesh, new Vector3(0, 0, 100), Quaternion.identity, font.material, 0);
}
if (GUI.Button(new Rect(200, 200, 100, 100), "Set Font"))
{
font = Font.CreateDynamicFontFromOSFont("Helvetica", 16);
// Request characters.
font.RequestCharactersInTexture(str);
// Set up mesh.
mesh = new Mesh();
// Generate font mesh.
RebuildMesh();
}
}
void OnUpdate()
{
font.RequestCharactersInTexture(str);
}
}
}

3
Assets/UIWidgets/editor/TextMesh.cs.meta


fileFormatVersion: 2
guid: 3f658931d0dc4f06817e18cb3a999189
timeCreated: 1535014129

3
Assets/UIWidgets/math.meta


fileFormatVersion: 2
guid: c53bae489a2f499ea5b9000edb31b0bb
timeCreated: 1535421229

288
Assets/UIWidgets/painting/text_painter.cs


using System;
using System.Runtime.ConstrainedExecution;
using UIWidgets.math;
using UIWidgets.ui;
using UnityEngine;
using Canvas = UIWidgets.ui.Canvas;
namespace UIWidgets.painting
{
public class TextPainter
{
private TextSpan _text;
private TextAlign _textAlign;
private TextDirection? _textDirection;
private double _textScaleFactor;
private Paragraph _layoutTemplate;
private Paragraph _paragraph;
private bool _needsLayout = true;
private int _maxLines;
private string _ellipsis;
private double _lastMinWidth;
private double _lastMaxWidth;
public TextPainter(TextSpan text,
TextAlign textAlign = TextAlign.left,
TextDirection textDirection = TextDirection.ltr,
double textScaleFactor = 1.0,
int maxLines = 0,
string ellipsis = "")
{
_text = text;
_textAlign = textAlign;
_textDirection = textDirection;
_textScaleFactor = textScaleFactor;
_maxLines = maxLines;
_ellipsis = ellipsis;
}
public double textScaleFactor
{
get { return _textScaleFactor; }
set
{
if (_textScaleFactor == value)
return;
_textScaleFactor = value;
_paragraph = null;
_layoutTemplate = null;
_needsLayout = true;
}
}
public string ellipsis
{
get { return _ellipsis; }
set
{
if (_ellipsis == value)
{
return;
}
_ellipsis = value;
_paragraph = null;
_needsLayout = true;
}
}
public TextSpan text
{
get { return _text; }
set
{
if (text.Equals(value))
{
return;
}
if (!Equals(_text == null ? null : _text.style, value == null ? null : value.style))
{
_layoutTemplate = null;
}
_text = value;
_paragraph = null;
_needsLayout = true;
}
}
public Size size
{
get
{
Debug.Assert(!_needsLayout);
return new Size(width, height);
}
}
public TextDirection? textDirection
{
get { return _textDirection; }
set
{
if (textDirection == value)
{
return;
}
_textDirection = value;
_paragraph = null;
_layoutTemplate = null;
_needsLayout = true;
}
}
public TextAlign textAlign
{
get { return _textAlign; }
set
{
if (_textAlign == value)
{
return;
}
_textAlign = value;
_paragraph = null;
_needsLayout = true;
}
}
public bool didExceedMaxLines
{
get
{
Debug.Assert(!_needsLayout);
return _paragraph.didExceedMaxLines;
}
}
public int maxLines
{
get { return _maxLines; }
set
{
if (_maxLines == value)
{
return;
}
_maxLines = value;
_paragraph = null;
_needsLayout = true;
}
}
public double minIntrinsicWidth
{
get
{
Debug.Assert(!_needsLayout);
return _applyFloatingPointHack(_paragraph.minIntrinsicWidth);
}
}
public double maxIntrinsicWidth
{
get
{
Debug.Assert(!_needsLayout);
return _applyFloatingPointHack(_paragraph.maxIntrinsicWidth);
}
}
public double height
{
get
{
Debug.Assert(!_needsLayout);
return _applyFloatingPointHack(_paragraph.height);
}
}
public double width
{
get
{
Debug.Assert(!_needsLayout);
return _applyFloatingPointHack(_paragraph.width);
}
}
public double computeDistanceToActualBaseline(TextBaseline baseline)
{
Debug.Assert(!_needsLayout);
switch (baseline)
{
case TextBaseline.alphabetic:
return _paragraph.alphabeticBaseline;
case TextBaseline.ideographic:
return _paragraph.ideographicBaseline;
}
return 0.0;
}
public void layout(double minWidth = 0.0, double maxWidth = double.PositiveInfinity)
{
Debug.Assert(text != null, "TextPainter.text must be set to a non-null value before using the TextPainter.");
Debug.Assert(textDirection != null, "TextPainter.textDirection must be set to a non-null value before using the TextPainter.");
if (_needsLayout && minWidth == _lastMaxWidth && maxWidth == _lastMaxWidth)
{
return;
}
_needsLayout = false;
if (_paragraph == null)
{
var builder = new ParagraphBuilder(_createParagraphStyle());
_text.build(builder, textScaleFactor);
_paragraph = builder.build();
}
_lastMinWidth = minWidth;
_lastMaxWidth = minWidth;
_paragraph.layout(new ParagraphConstraints(maxWidth));
if (minWidth != maxWidth)
{
var newWidth = MathUtil.Clamp(maxIntrinsicWidth, minWidth, maxWidth);
if (newWidth != width)
{
_paragraph.layout(new ParagraphConstraints(newWidth));
}
}
}
public void paint(Canvas canvas, Offset offset)
{
Debug.Assert(_needsLayout);
_paragraph.paint(canvas, offset.dx, offset.dy);
}
private ParagraphStyle _createParagraphStyle(TextDirection defaultTextDirection = TextDirection.ltr)
{
if (_text.style == null)
{
return new ParagraphStyle(
textAlign: textAlign,
textDirection: textDirection ?? defaultTextDirection,
maxLines: maxLines,
ellipsis: ellipsis
);
}
return _text.style.getParagraphStyle(textAlign, textDirection ?? defaultTextDirection,
ellipsis, maxLines, textScaleFactor);
}
public double preferredLineHeight
{
get
{
if (_layoutTemplate == null)
{
var builder = new ParagraphBuilder(
_createParagraphStyle(TextDirection.ltr)
); // direction doesn't matter, text is just a space
if (text != null && text.style != null)
{
builder.pushStyle(text.style.getTextStyle(textScaleFactor));
}
builder.addText(" ");
_layoutTemplate = builder.build();
_layoutTemplate.layout(new ParagraphConstraints(double.PositiveInfinity));
}
return _layoutTemplate.height;
}
}
private double _applyFloatingPointHack(double layoutValue)
{
return Math.Ceiling(layoutValue);
}
}
}

3
Assets/UIWidgets/painting/text_painter.cs.meta


fileFormatVersion: 2
guid: 23fd2d1247bf4e308d9f88f3488da38f
timeCreated: 1535348672

246
Assets/UIWidgets/painting/text_span.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UIWidgets.ui;
using UnityEditor;
using UnityEngine.Assertions;
namespace UIWidgets.painting
{
public class GestureMock
{
}
public class TextSpan: IEquatable<TextSpan>
{
public delegate bool Visitor(TextSpan span);
public readonly TextStyle style;
public readonly string text;
public readonly List<TextSpan> children;
public readonly GestureMock recognizer;
public TextSpan(TextStyle style, string text, List<TextSpan> children)
{
this.text = text;
this.style = style;
this.children = children;
}
public void build(ParagraphBuilder builder, double textScaleFactor = 1.0)
{
var hasTyle = style != null;
if (hasTyle)
{
builder.pushStyle(style.getTextStyle(textScaleFactor));
}
if (!string.IsNullOrEmpty(text))
{
builder.addText(text);
}
if (children != null)
{
foreach (var child in children)
{
Assert.IsNotNull(child);
child.build(builder, textScaleFactor);
}
}
if (hasTyle)
{
builder.pop();
}
}
bool visitTextSpan(Visitor visitor)
{
if (!string.IsNullOrEmpty(text))
{
if (!visitor.Invoke(this))
{
return false;
}
}
if (children != null)
{
foreach (var child in children)
{
if (!child.visitTextSpan(visitor))
{
return false;
}
}
}
return true;
}
TextSpan getSpanForPosition(TextPosition position)
{
var offset = 0;
var targetOffset = position.offset;
var affinity = position.affinity;
TextSpan result = null;
visitTextSpan((span) =>
{
var endOffset = offset + span.text.Length;
if ((targetOffset == offset && affinity == TextAffinity.downstream) ||
(targetOffset > offset && targetOffset < endOffset) ||
(targetOffset == endOffset && affinity == TextAffinity.upstream))
{
result = span;
return false;
}
offset = endOffset;
return true;
});
return result;
}
string toPlainText()
{
var sb = new StringBuilder();
visitTextSpan((span) =>
{
sb.Append(span.text);
return true;
});
return sb.ToString();
}
public int codeUnitAt(int index)
{
if (index < 0)
{
return -1;
}
var offset = 0;
var result = -1;
visitTextSpan(span =>
{
if (index - offset < span.text.Length)
{
result = span.text[index - offset];
return false;
}
offset += span.text.Length;
return true;
});
return result;
}
public RenderComparison compareTo(TextSpan other)
{
if (Equals(other))
{
return RenderComparison.identical;
}
if (other.text != text
|| ((children == null) != (other.children == null))
|| (children != null && other.children != null && children.Count != other.children.Count)
|| ((style == null) != (other.style != null))
)
{
return RenderComparison.layout;
}
RenderComparison result = Equals(recognizer, other.recognizer)
? RenderComparison.identical
: RenderComparison.metadata;
if (style != null)
{
var candidate = style.compareTo(other.style);
if (candidate > result)
{
result = candidate;
}
if (result == RenderComparison.layout)
{
return result;
}
}
if (children != null)
{
for (var index = 0; index < children.Count; index++)
{
var candidate = children[index].compareTo(other.children[index]);
if (candidate > result)
{
result = candidate;
}
if (result == RenderComparison.layout)
{
return result;
}
}
}
return result;
}
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((TextSpan) obj);
}
public override int GetHashCode()
{
unchecked
{
var hashCode = (style != null ? style.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (text != null ? text.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (childHash());
return hashCode;
}
}
public bool Equals(TextSpan other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return Equals(style, other.style) && string.Equals(text, other.text) && childEquals(children, other.children);
}
private int childHash()
{
unchecked
{
var hashCode = 0;
if (children != null)
{
foreach (var child in children)
{
hashCode = (hashCode * 397) ^ (child != null ? child.GetHashCode() : 0);
}
}
return hashCode;
}
}
private static bool childEquals(List<TextSpan> left, List<TextSpan> right)
{
if (ReferenceEquals(left, right))
{
return true;
}
if (left == null || right == null)
{
return false;
}
return left.SequenceEqual(right);
}
}
}

84
Assets/UIWidgets/painting/text_style.cs


using System;
using UIWidgets.painting;
using UIWidgets.ui;
namespace UIWidgets.painting
{
public class TextStyle
{
public static readonly double _defaultFontSize = 14.0;
public readonly bool? inherit;
public readonly Color color;
public readonly double? fontSize;
public readonly FontWeight? fontWeight;
public readonly FontStyle? fontStyle;
public readonly double? letterSpacing;
public readonly double? wordSpacing;
public readonly TextBaseline? textBaseline;
public readonly double? height;
public readonly TextDecoration decoration;
public readonly string fontFamily;
public TextStyle(bool? inherit, Color color, double? fontSize, FontWeight? fontWeight,
FontStyle? fontStyle, double? letterSpacing, double? wordSpacing,
TextBaseline? textBaseline, double? height, TextDecoration decoration)
{
this.inherit = inherit;
this.color = color;
this.fontSize = fontSize;
this.fontWeight = fontWeight;
this.fontStyle = fontStyle;
this.letterSpacing = letterSpacing;
this.wordSpacing = wordSpacing;
this.textBaseline = textBaseline;
this.height = height;
this.decoration = decoration;
}
public ui.TextStyle getTextStyle(double textScaleFactor = 1.0)
{
return new ui.TextStyle(
color: color,
decoration: decoration,
fontWeight: fontWeight,
fontSize: fontSize == null ? null : fontSize * textScaleFactor,
letterSpacing: letterSpacing,
wordSpacing: wordSpacing,
textBaseline: textBaseline,
height: height,
fontFamily: fontFamily
);
}
public RenderComparison compareTo(TextStyle other)
{
if (inherit != other.inherit || fontFamily != other.fontFamily
|| fontSize != other.fontSize || fontWeight != other.fontWeight
|| fontStyle != other.fontStyle || letterSpacing != other.letterSpacing
|| wordSpacing != other.wordSpacing || textBaseline != other.textBaseline
|| height != other.height)
{
return RenderComparison.layout;
}
if (color != other.color || decoration != other.decoration)
{
return RenderComparison.paint;
}
return RenderComparison.identical;
}
public ParagraphStyle getParagraphStyle(TextAlign textAlign,
TextDirection textDirection, string ellipsis, int maxLines, double textScaleFactor = 1.0)
{
return new ParagraphStyle(
textAlign, textDirection, fontWeight, fontStyle,
maxLines, (fontSize ?? _defaultFontSize) * textScaleFactor,
fontFamily, height, ellipsis
);
}
}
}

3
Assets/UIWidgets/painting/text_style.cs.meta


fileFormatVersion: 2
guid: 93d2ea584e0947e1b61a8ca8bdd1cf9a
timeCreated: 1535348621

235
Assets/UIWidgets/rendering/paragraph.cs


using System;
using UIWidgets.painting;
using UIWidgets.ui;
using UnityEngine;
namespace UIWidgets.rendering
{
public enum TextOverflow {
/// Clip the overflowing text to fix its container.
clip,
/// Fade the overflowing text to transparent.
fade,
/// Use an ellipsis to indicate that the text has overflowed.
ellipsis,
}
public class RenderParagraph: RenderBox
{
private static readonly string _kEllipsis = "\u2026";
private bool _softWrap;
private TextOverflow _overflow;
private readonly TextPainter _textPainter;
private bool _hasVisualOverflow = false;
public RenderParagraph(TextSpan text,
TextAlign textAlign = TextAlign.left,
TextDirection textDirection = TextDirection.ltr,
bool softWrap = true,
TextOverflow overflow = TextOverflow.clip,
double textScaleFactor = 1.0,
int maxLines = 0
)
{
_softWrap = softWrap;
_overflow = overflow;
_textPainter = new TextPainter(
text,
textAlign,
textDirection,
textScaleFactor,
maxLines,
overflow == TextOverflow.ellipsis ? _kEllipsis : ""
);
}
public TextSpan text
{
get
{
return _textPainter.text;
}
set
{
Debug.Assert(value != null);
switch (_textPainter.text.compareTo(value))
{
case RenderComparison.identical:
case RenderComparison.metadata:
return;
case RenderComparison.paint:
_textPainter.text = value;
markNeedsPaint();
break;
case RenderComparison.layout:
_textPainter.text = value;
markNeedsLayout();
break;
}
}
}
public TextAlign textAlign
{
get { return _textPainter.textAlign; }
set
{
if (_textPainter.textAlign == value)
{
return;
}
_textPainter.textAlign = value;
markNeedsPaint();
}
}
public TextDirection? textDirection
{
get { return _textPainter.textDirection; }
set
{
if (_textPainter.textDirection == value)
{
return;
}
_textPainter.textDirection = textDirection;
markNeedsLayout();
}
}
public bool softWrap
{
get { return _softWrap; }
set
{
if (_softWrap == value)
{
return;
}
_softWrap = value;
markNeedsLayout();
}
}
public TextOverflow overflow
{
get { return _overflow; }
set
{
if (_overflow == value)
{
return;
}
_overflow = value;
_textPainter.ellipsis = value == TextOverflow.ellipsis ? _kEllipsis : null;
// _textPainter.e
markNeedsLayout();
}
}
public double textScaleFactor
{
get { return _textPainter.textScaleFactor; }
set
{
if (Math.Abs(_textPainter.textScaleFactor - value) < 0.00000001)
{
return;
}
_textPainter.textScaleFactor = value;
markNeedsLayout();
}
}
public int maxLines
{
get { return _textPainter.maxLines; }
set
{
if (_textPainter.maxLines == value)
{
return;
}
_textPainter.maxLines = value;
markNeedsLayout();
}
}
public Size textSize
{
get { return _textPainter.size; }
}
public override double computeMinIntrinsicWidth(double height) {
_layoutText();
return _textPainter.minIntrinsicWidth;
}
public override double computeMaxIntrinsicWidth(double height) {
_layoutText();
return _textPainter.maxIntrinsicWidth;
}
double _computeIntrinsicHeight(double width) {
_layoutText(minWidth: width, maxWidth: width);
return _textPainter.height;
}
public override double computeMinIntrinsicHeight(double width) {
return _computeIntrinsicHeight(width);
}
public override double computeMaxIntrinsicHeight(double width) {
return _computeIntrinsicHeight(width);
}
public override double? computeDistanceToActualBaseline(TextBaseline baseline) {
_layoutTextWithConstraints(constraints);
return _textPainter.computeDistanceToActualBaseline(baseline);
}
public override void performLayout() {
_layoutTextWithConstraints(constraints);
var textSize = _textPainter.size;
var didOverflowHeight = _textPainter.didExceedMaxLines;
size = constraints.constrain(textSize);
var didOverflowWidth = size.width < textSize.width;
_hasVisualOverflow = didOverflowWidth || didOverflowHeight;
}
public override void paint(PaintingContext context, Offset offset) {
_layoutTextWithConstraints(constraints);
var canvas = context.canvas;
if (_hasVisualOverflow) {
var bounds = offset & size;
canvas.save();
canvas.clipRect(bounds);
}
_textPainter.paint(canvas, offset);
if (_hasVisualOverflow) {
canvas.restore();
}
}
private void _layoutText(double minWidth = 0.0, double maxWidth = double.PositiveInfinity)
{
var widthMatters = softWrap || overflow == TextOverflow.ellipsis;
_textPainter.layout(minWidth, widthMatters ? maxWidth : double.PositiveInfinity);
}
private void _layoutTextWithConstraints(BoxConstraints constraints) {
_layoutText(minWidth: constraints.minWidth, maxWidth: constraints.maxWidth);
}
}
}

3
Assets/UIWidgets/rendering/paragraph.cs.meta


fileFormatVersion: 2
guid: 69e1c7c86f0d4f4e9aae4c3131653270
timeCreated: 1535348727

3
Assets/UIWidgets/ui/txt.meta


fileFormatVersion: 2
guid: 00abcb769ae345788c13376e3170023b
timeCreated: 1535349060

14
Assets/UIWidgets/math/math.cs


namespace UIWidgets.math
{
public class MathUtil
{
public static double Clamp(double value, double min, double max)
{
if ((double) value < (double) min)
value = min;
else if ((double) value > (double) max)
value = max;
return value;
}
}
}

3
Assets/UIWidgets/math/math.cs.meta


fileFormatVersion: 2
guid: b170f0bc9c074368b3be9db736974c6f
timeCreated: 1535421239

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


using System;
using System.Collections.Generic;
using UnityEngine;
namespace UIWidgets.ui
{
public class LineBreaker
{
public class LineInfo
{
public int start;
public double width;
}
private StyledRuns _runs;
public Vector2[] _characterPositions;
public float[] _characterWidth;
// private List<int> breaks;
private string _text;
private float _width;
private int _lineStart;
private int _wordStart;
// private int _preWordEnd;
private int _runIndex = 0;
private int _spaceCount = 0;
private int tabCount = 4;
private double _lineLength;
private List<LineInfo> _lines;
// private double lengths
public void setup(string text, StyledRuns runs, float width, Vector2[] characterPositions, float[] characterWidth)
{
_text = text;
_runs = runs;
_characterPositions = characterPositions;
_characterWidth = characterWidth;
_width = width;
}
public List<LineInfo> getLines()
{
return _lines;
}
public void doBreak(int blockStart, int blockEnd)
{
_lines = new List<LineInfo>();
float offsetX = 0.0f;
for (var charIndex = blockStart; charIndex < blockEnd; charIndex++)
{
var run = _runs.getRun(_runIndex);
while ((run == null || run.end <= charIndex || charIndex < run.start) &&
_runIndex + 1 < _runs.size)
{
_runIndex++;
run = _runs.getRun(_runIndex);
}
if (run.start == charIndex)
{
run.font.RequestCharactersInTexture(_text.Substring(run.start, run.end - run.start), run.style.UnityFontSize, run.style.UnityFontStyle);
}
var style = run.style;
var font = run.font;
CharacterInfo charInfo;
var result = font.GetCharacterInfo(_text[charIndex], out charInfo);
// _characterSize[charIndex] = style.UnityFontSize;
//
if (_text[charIndex] == '\t')
{
_spaceCount++;
font.GetCharacterInfo(' ', out charInfo,
style.UnityFontSize, style.UnityFontStyle);
float tabSize = charInfo.advance * tabCount;
var newX = (float)Math.Floor(((offsetX / tabSize) + 1) * tabSize);
if (newX > _width && _lineStart != charIndex)
{
_characterWidth[charIndex] = tabSize;
makeLine(charIndex, charIndex);
}
else
{
_characterWidth[charIndex] = newX - offsetX;
_characterPositions[charIndex].x = offsetX;
}
offsetX = _characterPositions[charIndex].x + _characterWidth[charIndex];
}
else if (_text[charIndex] == ' ')
{
_spaceCount++;
_characterPositions[charIndex].x = offsetX;
_characterWidth[charIndex] = charInfo.advance;
offsetX = _characterPositions[charIndex].x + _characterWidth[charIndex];
// todo no wrap in space ?
}
else
{
if (_spaceCount > 0 || blockStart == charIndex)
{
_wordStart = charIndex;
}
_characterPositions[charIndex].x = offsetX;
_characterWidth[charIndex] = charInfo.advance;
if (offsetX + charInfo.advance > _width && _lineStart != charIndex)
{
if (_lineStart == _wordStart)
{
makeLine(charIndex, charIndex);
_wordStart = charIndex;
}
else
{
makeLine(_wordStart, charIndex);
}
}
offsetX = _characterPositions[charIndex].x + _characterWidth[charIndex];
_spaceCount = 0;
}
/*
* CharacterInfo charInfo;
context.font.GetCharacterInfo(c, out charInfo,
context.style.UnityFontSize, context.style.UnityFontStyle);
_characterInfos[context.index] = charInfo;
_characterPositions[context.index].x = context.offset.x;
// _characterPositions[context.index].y = context.offset.y;
if (context.offset.x + charInfo.advance > _width)
{
wordWrap(context);
}
return null;
*/
}
makeLine(blockEnd, blockEnd);
}
private void makeLine(int end, int last)
{
Debug.Assert(_lineStart < end);
Debug.Assert(end <= last);
_lines.Add(new LineInfo()
{
start = _lineStart,
width = _characterPositions[end - 1].x + _characterWidth[end - 1],
});
_lineStart = end;
if (end >= _characterPositions.Length)
{
return;
}
var offset = new Vector2(-_characterPositions[end].x, 0);
_characterPositions[end].x = 0;
if (end < last)
{
Paragraph.offsetCharacters(offset,
_characterPositions, end + 1, last + 1);
}
}
}
}

3
Assets/UIWidgets/ui/txt/linebreaker.cs.meta


fileFormatVersion: 2
guid: 05dff99bf5a0462da5c4c9c7b7d1b3dc
timeCreated: 1535533476

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


using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.Assertions;
namespace UIWidgets.ui
{
public class Paragraph
{
class LineRange
{
public LineRange(int start, int end, int endExcludingWhitespace, int endIncludingNewLine, bool hardBreak)
{
this.start = start;
this.end = end;
this.endExcludingWhitespace = endExcludingWhitespace;
this.endIncludingNewLine = endIncludingNewLine;
this.hardBreak = hardBreak;
}
public readonly int start;
public readonly int end;
public readonly int endExcludingWhitespace;
public readonly int endIncludingNewLine;
public readonly bool hardBreak;
}
class LayoutContext
{
public int width;
public int index;
public Vector2 offset;
public TextStyle style;
public Font font;
public int wordStart;
public int lineStart;
public int prevWordEnd;
}
private bool _needsLayout = true;
private string _text;
private StyledRuns _runs;
private ParagraphStyle _paragraphStyle;
private List<LineRange> _lineRanges = new List<LineRange>();
private List<double> _lineWidths = new List<double>();
private Vector2[] _characterPositions;
private CharacterInfo[] _characterInfos;
private Font[] _fonts;
private float[] _characterWidths;
private float[] _characterSize;
private LayoutContext context;
// private double _characterWidth;
private double _width;
// mesh
//
public double height
{
get { return 0.0; }
}
public double minIntrinsicWidth
{
get { return 0.0; }
}
public double maxIntrinsicWidth
{
get { return 0.0; }
}
public double width
{
get { return 0.0; }
}
public double alphabeticBaseline
{
get { return 0.0; }
}
public double ideographicBaseline
{
get { return 0.0; }
}
public bool didExceedMaxLines
{
get { return false; }
}
public void paint(Canvas canvas, double x, double y)
{
var mesh = generateMesh();
}
public void layout(ParagraphConstraints constraints)
{
// if (!_needsLayout && _width == constraints.width)
// {
// return;
// }
_needsLayout = false;
_width = Math.Floor(constraints.width);
this.setup();
computeLineBreak();
layoutLines();
}
public void setText(string text, StyledRuns runs)
{
_text = text;
_runs = runs;
_needsLayout = true;
}
public void setParagraphStyle(ParagraphStyle style)
{
_needsLayout = true;
_paragraphStyle = style;
}
public static void offsetCharacters(Vector2 offset, Vector2[] characterPos, int start, int end)
{
if (characterPos != null)
{
for (int i = start; i < characterPos.Length && i < end; ++i)
{
characterPos[i] = characterPos[i] + offset;
}
}
}
private Offset insertCharacter(char c, LayoutContext context)
{
CharacterInfo charInfo;
context.font.GetCharacterInfo(c, out charInfo,
context.style.UnityFontSize, context.style.UnityFontStyle);
_characterInfos[context.index] = charInfo;
_characterPositions[context.index].x = context.offset.x;
// _characterPositions[context.index].y = context.offset.y;
if (context.offset.x + charInfo.advance > _width)
{
wordWrap(context);
}
return null;
}
private void wordWrap(LayoutContext context)
{
if (context.wordStart == context.lineStart)
{
context.wordStart = context.index;
}
}
private void setup()
{
_characterPositions = new Vector2[_text.Length];
_characterInfos = new CharacterInfo[_text.Length];
_characterSize = new float[_text.Length];
_characterWidths = new float[_text.Length];
_fonts = new Font[_text.Length];
// for (var i = 0; i < _runs.size; i++)
// {
// var run = _runs.getRun(i);
// // run.font.RequestCharactersInTexture(_text.Substring(run.start, run.end - run.start), run.font.fontSize, run.) ;
// }
}
// private void layoutBlock(int start, int end, ref int styleIndex)
// {
//
// }
private void layoutLines()
{
double yOffset = 0;
var runIndex = 0;
double lastDescent = 0.0f;
for (int i = 0; i < _lineRanges.Count; i++)
{
var line = _lineRanges[i];
double maxAscent = 0.0f;
double maxDescent = 0.0f;
for (;runIndex < _runs.size;runIndex++)
{
var run = _runs.getRun(runIndex);
var ascent = run.font.ascent * (run.style.height??1.0);
var descent = (run.font.lineHeight - run.font.ascent) * (run.style.height??1.0);
if (ascent > maxAscent)
{
maxAscent = ascent;
}
if (descent > maxDescent)
{
maxDescent = descent;
}
if (runIndex + 1 < _runs.size)
{
var nextRun = _runs.getRun(runIndex + 1);
if (nextRun.start >= line.end)
{
break;
}
}
}
lastDescent = maxDescent;
yOffset += maxAscent + lastDescent;
for (var charIndex = line.start; charIndex < line.end; charIndex++)
{
_characterPositions[charIndex].y = (float)yOffset;
}
}
}
private void computeLineBreak()
{
_lineRanges.Clear();
_lineWidths.Clear();
var newLinePositions = new List<int>();
for (var i = 0; i < _text.Length; i++)
{
if (_text[i] == '\n')
{
newLinePositions.Add(i);
}
}
newLinePositions.Add(_text.Length);
int runIndex = 0;
StyledRuns.Run lastRun = null;
var lineBreaker = new LineBreaker();
lineBreaker.setup(_text, _runs, (float)_width, _characterPositions, _characterWidths);
for (var newlineIndex = 0; newlineIndex < newLinePositions.Count; ++newlineIndex)
{
var blockStart = newlineIndex > 0 ? newLinePositions[newlineIndex - 1] + 1 : 0;
var blockEnd = newLinePositions[newlineIndex];
var blockSize = blockEnd - blockStart;
if (blockSize == 0)
{
_lineRanges.Add(new LineRange(blockStart, blockEnd, blockEnd, blockEnd + 1, true));
_lineWidths.Add(0);
}
lineBreaker.doBreak(blockStart, blockEnd);
var lines = lineBreaker.getLines();
for (int i = 0; i < lines.Count; ++i)
{
var line = lines[i];
var end = i + 1 < lines.Count ? lines[i + 1].start : blockEnd;
var nonWhiteSpace = end - 1;
while (nonWhiteSpace >= line.start && _text[nonWhiteSpace] == ' ' || _text[nonWhiteSpace] == '\t')
{
nonWhiteSpace--;
}
_lineRanges.Add(new LineRange(line.start, end, nonWhiteSpace, end + 1, end == blockEnd));
_lineWidths.Add(line.width);
}
}
return;
}
private Mesh generateMesh()
{
var vertices = new Vector3[_text.Length * 4];
var triangles = new int[_text.Length * 6];
var uv = new Vector2[_text.Length * 4];
Vector3 pos = Vector3.zero;
int runIndex = 0;
for (int charIndex = 0; charIndex < _text.Length; charIndex++)
{
var run = _runs.getRun(runIndex);
while ((run == null || run.end <= charIndex || charIndex < run.start) &&
charIndex + 1 < _runs.size)
{
charIndex++;
run = _runs.getRun(charIndex);
}
if (run.start == charIndex)
{
run.font.RequestCharactersInTexture(_text.Substring(run.start, run.end - run.start), run.style.UnityFontSize, run.style.UnityFontStyle);
}
CharacterInfo charInfo;
var result = run.font.GetCharacterInfo(_text[charIndex], out charInfo);
var position = _characterPositions[charIndex];
vertices[4 * charIndex + 0] = pos + new Vector3(charInfo.minX, position.y - charInfo.maxY, 0);
vertices[4 * charIndex + 1] = pos + new Vector3(charInfo.maxX, position.y - charInfo.maxY, 0);
vertices[4 * charIndex + 2] = pos + new Vector3(charInfo.maxX, position.y + charInfo.minY, 0);
vertices[4 * charIndex + 3] = pos + new Vector3(charInfo.minX, position.y + charInfo.minY, 0);
uv[4 * charIndex + 0] = charInfo.uvTopLeft;
uv[4 * charIndex + 1] = charInfo.uvTopRight;
uv[4 * charIndex + 2] = charInfo.uvBottomRight;
uv[4 * charIndex + 3] = charInfo.uvBottomLeft;
triangles[6 * charIndex + 0] = 4 * charIndex + 0;
triangles[6 * charIndex + 1] = 4 * charIndex + 1;
triangles[6 * charIndex + 2] = 4 * charIndex + 2;
triangles[6 * charIndex + 3] = 4 * charIndex + 0;
triangles[6 * charIndex + 4] = 4 * charIndex + 2;
triangles[6 * charIndex + 5] = 4 * charIndex + 3;
}
var mesh = new Mesh()
{
vertices = vertices,
triangles = triangles,
uv = uv
};
return mesh;
}
}
}

3
Assets/UIWidgets/ui/txt/paragraph.cs.meta


fileFormatVersion: 2
guid: 8c81399e7e914dedaee84b52748d4ac0
timeCreated: 1535349134

75
Assets/UIWidgets/ui/txt/paragraph_builder.cs


using System.Collections.Generic;
using System.Text;
namespace UIWidgets.ui
{
public class ParagraphBuilder
{
private StringBuilder _text = new StringBuilder();
private ParagraphStyle _paragraphStyle;
private StyledRuns _runs = new StyledRuns();
private List<int> _styleStack = new List<int>();
private int _paragraph_style_index;
public ParagraphBuilder(ParagraphStyle style)
{
setParagraphStyle(style);
}
public Paragraph build()
{
var paragraph = new Paragraph();
paragraph.setText(_text.ToString(), _runs);
paragraph.setParagraphStyle(_paragraphStyle);
return paragraph;
}
public void pushStyle(TextStyle style)
{
var newStyle = peekStyle().merge(style);
var styleIndex = _runs.addStyle(newStyle);
_styleStack.Add(styleIndex);
_runs.startRun(styleIndex, _text.Length);
}
public void pop()
{
var lastIndex = _styleStack.Count - 1;
if (lastIndex < 0)
{
return;
}
_styleStack.RemoveAt(lastIndex);
_runs.startRun(peekStyleIndex(), _text.Length);
}
public void addText(string text)
{
this._text.Append(text);
}
public TextStyle peekStyle()
{
return _runs.getStyle(peekStyleIndex());
}
public int peekStyleIndex() {
int count = _styleStack.Count;
if (count > 0)
{
return _styleStack[count - 1];
}
return _paragraph_style_index;
}
private void setParagraphStyle(ParagraphStyle style)
{
_paragraphStyle = style;
_paragraph_style_index = _runs.addStyle(style.getTextStyle());
_runs.startRun(_paragraph_style_index, _text.Length);
}
}
}

3
Assets/UIWidgets/ui/txt/paragraph_builder.cs.meta


fileFormatVersion: 2
guid: 869d4277d11048c397fc1fdb3abe3c02
timeCreated: 1535349090

113
Assets/UIWidgets/ui/txt/styled_runs.cs


using System.Collections.Generic;
using UnityEngine;
namespace UIWidgets.ui
{
public class StyledRuns
{
private readonly List<TextStyle> styles = new List<TextStyle>();
private readonly List<IndexedRun> runs = new List<IndexedRun>();
public class Run
{
public readonly TextStyle style;
public readonly int start;
public readonly int end;
public Font _font;
public Run(TextStyle style, int start, int end)
{
this.style = style;
this.start = start;
this.end = end;
}
public Font font
{
get
{
if (_font == null)
{
_font = Font.CreateDynamicFontFromOSFont(style.safeFontFamily,
(style.UnityFontSize));
}
return _font;
}
}
}
public class IndexedRun
{
public readonly int styleIndex = 0;
public readonly int start;
public int end;
public IndexedRun(int styleIndex, int start, int end)
{
this.styleIndex = styleIndex;
this.start = start;
this.end = end;
}
}
public StyledRuns()
{
}
public StyledRuns(StyledRuns other)
{
styles = new List<TextStyle>(other.styles);
runs = new List<IndexedRun>(other.runs);
}
public int addStyle(TextStyle style)
{
var styleIndex = styles.Count;
styles.Add( style);
return styleIndex;
}
public TextStyle getStyle(int index)
{
return styles[index];
}
public void startRun(int styleIndex, int start)
{
endRunIfNeeded(start);
runs.Add(new IndexedRun(styleIndex, start, start));
}
public void endRunIfNeeded(int end)
{
var lastIndex = runs.Count - 1;
if (lastIndex < 0)
{
return;
}
var run = runs[lastIndex];
if (run.start == end)
{
runs.RemoveAt(lastIndex);
}
else
{
run.end = end;
}
}
public Run getRun(int index)
{
var run = runs[index];
return new Run(styles[run.styleIndex], run.start, run.end);
}
public int size
{
get { return runs.Count; }
}
}
}

3
Assets/UIWidgets/ui/txt/styled_runs.cs.meta


fileFormatVersion: 2
guid: 3f314adfc2d8498d827e5501599b0f5a
timeCreated: 1535434217
正在加载...
取消
保存