fzhangtj
6 年前
当前提交
d5a10357
共有 31 个文件被更改,包括 2253 次插入 和 1 次删除
-
5Assets/UIWidgets/Tests/Menu.cs
-
11Assets/UIWidgets/painting/basic_types.cs
-
2Assets/UIWidgets/rendering/viewpoint.cs
-
1Assets/UIWidgets/ui/painting/canvas.cs
-
4Assets/UIWidgets/ui/painting/draw_cmd.cs
-
394Assets/UIWidgets/ui/text.cs
-
103Assets/UIWidgets/Tests/Text.cs
-
3Assets/UIWidgets/Tests/Text.cs.meta
-
118Assets/UIWidgets/editor/TextMesh.cs
-
3Assets/UIWidgets/editor/TextMesh.cs.meta
-
3Assets/UIWidgets/math.meta
-
288Assets/UIWidgets/painting/text_painter.cs
-
3Assets/UIWidgets/painting/text_painter.cs.meta
-
246Assets/UIWidgets/painting/text_span.cs
-
84Assets/UIWidgets/painting/text_style.cs
-
3Assets/UIWidgets/painting/text_style.cs.meta
-
235Assets/UIWidgets/rendering/paragraph.cs
-
3Assets/UIWidgets/rendering/paragraph.cs.meta
-
3Assets/UIWidgets/ui/txt.meta
-
14Assets/UIWidgets/math/math.cs
-
3Assets/UIWidgets/math/math.cs.meta
-
177Assets/UIWidgets/ui/txt/linebreaker.cs
-
3Assets/UIWidgets/ui/txt/linebreaker.cs.meta
-
348Assets/UIWidgets/ui/txt/paragraph.cs
-
3Assets/UIWidgets/ui/txt/paragraph.cs.meta
-
75Assets/UIWidgets/ui/txt/paragraph_builder.cs
-
3Assets/UIWidgets/ui/txt/paragraph_builder.cs.meta
-
113Assets/UIWidgets/ui/txt/styled_runs.cs
-
3Assets/UIWidgets/ui/txt/styled_runs.cs.meta
|
|||
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; |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
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) |
|||
})) |
|||
); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: f4121086094d45de9e29781269270102 |
|||
timeCreated: 1535424100 |
|
|||
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); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 3f658931d0dc4f06817e18cb3a999189 |
|||
timeCreated: 1535014129 |
|
|||
fileFormatVersion: 2 |
|||
guid: c53bae489a2f499ea5b9000edb31b0bb |
|||
timeCreated: 1535421229 |
|
|||
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); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 23fd2d1247bf4e308d9f88f3488da38f |
|||
timeCreated: 1535348672 |
|
|||
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); |
|||
} |
|||
} |
|||
} |
|
|||
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 |
|||
); |
|||
} |
|||
|
|||
|
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 93d2ea584e0947e1b61a8ca8bdd1cf9a |
|||
timeCreated: 1535348621 |
|
|||
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); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 69e1c7c86f0d4f4e9aae4c3131653270 |
|||
timeCreated: 1535348727 |
|
|||
fileFormatVersion: 2 |
|||
guid: 00abcb769ae345788c13376e3170023b |
|||
timeCreated: 1535349060 |
|
|||
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; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: b170f0bc9c074368b3be9db736974c6f |
|||
timeCreated: 1535421239 |
|
|||
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); |
|||
} |
|||
} |
|||
|
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 05dff99bf5a0462da5c4c9c7b7d1b3dc |
|||
timeCreated: 1535533476 |
|
|||
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; |
|||
} |
|||
|
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 8c81399e7e914dedaee84b52748d4ac0 |
|||
timeCreated: 1535349134 |
|
|||
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); |
|||
} |
|||
|
|||
|
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 869d4277d11048c397fc1fdb3abe3c02 |
|||
timeCreated: 1535349090 |
|
|||
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; } |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 3f314adfc2d8498d827e5501599b0f5a |
|||
timeCreated: 1535434217 |
撰写
预览
正在加载...
取消
保存
Reference in new issue