using System; using System.Collections.Generic; using UnityEngine; namespace FairyGUI { /// /// /// public class DynamicFont : BaseFont { Font _font; int _size; float _ascent; float _lineHeight; float _scale; TextFormat _format; FontStyle _style; bool _boldVertice; CharacterInfo _char; CharacterInfo _lineChar; bool _gotLineChar; public DynamicFont() { this.canTint = true; this.keepCrisp = true; this.customOutline = true; this.shader = ShaderConfig.textShader; } /// /// /// /// /// /// public DynamicFont(string name, Font font) : this() { this.name = name; this.nativeFont = font; } override public void Dispose() { Font.textureRebuilt -= textureRebuildCallback; } public Font nativeFont { get { return _font; } set { if (_font != null) Font.textureRebuilt -= textureRebuildCallback; _font = value; Font.textureRebuilt += textureRebuildCallback; _font.hideFlags = DisplayObject.hideFlags; _font.material.hideFlags = DisplayObject.hideFlags; _font.material.mainTexture.hideFlags = DisplayObject.hideFlags; if (mainTexture != null) mainTexture.Dispose(); mainTexture = new NTexture(_font.material.mainTexture); mainTexture.destroyMethod = DestroyMethod.None; // _ascent = _font.ascent; // _lineHeight = _font.lineHeight; _ascent = _font.fontSize; _lineHeight = _font.fontSize * 1.25f; } } override public void SetFormat(TextFormat format, float fontSizeScale) { _format = format; float size = format.size * fontSizeScale; if (keepCrisp) size *= UIContentScaler.scaleFactor; if (_format.specialStyle == TextFormat.SpecialStyle.Subscript || _format.specialStyle == TextFormat.SpecialStyle.Superscript) size *= SupScale; _size = Mathf.FloorToInt(size); if (_size == 0) _size = 1; _scale = (float)_size / _font.fontSize; if (format.bold && !customBold) { if (format.italic) { if (customBoldAndItalic) _style = FontStyle.Italic; else _style = FontStyle.BoldAndItalic; } else _style = FontStyle.Bold; } else { if (format.italic) _style = FontStyle.Italic; else _style = FontStyle.Normal; } _boldVertice = format.bold && (customBold || (format.italic && customBoldAndItalic)); format.FillVertexColors(vertexColors); } override public void PrepareCharacters(string text) { _font.RequestCharactersInTexture(text, _size, _style); } override public bool GetGlyph(char ch, out float width, out float height, out float baseline) { if (!_font.GetCharacterInfo(ch, out _char, _size, _style)) { if (ch == ' ') { //space may not be prepared, try again _font.RequestCharactersInTexture(" ", _size, _style); _font.GetCharacterInfo(ch, out _char, _size, _style); } else { width = height = baseline = 0; return false; } } width = _char.advance; height = _lineHeight * _scale; baseline = _ascent * _scale; if (_boldVertice) width++; if (_format.specialStyle == TextFormat.SpecialStyle.Subscript) { height /= SupScale; baseline /= SupScale; } else if (_format.specialStyle == TextFormat.SpecialStyle.Superscript) { height = height / SupScale + baseline * SupOffset; baseline *= (SupOffset + 1 / SupScale); } height = Mathf.RoundToInt(height); baseline = Mathf.RoundToInt(baseline); if (keepCrisp) { width /= UIContentScaler.scaleFactor; height /= UIContentScaler.scaleFactor; baseline /= UIContentScaler.scaleFactor; } return true; } static Vector3 bottomLeft; static Vector3 topLeft; static Vector3 topRight; static Vector3 bottomRight; static Vector2 uvBottomLeft; static Vector2 uvTopLeft; static Vector2 uvTopRight; static Vector2 uvBottomRight; static Color32[] vertexColors = new Color32[4]; static Vector3[] BOLD_OFFSET = new Vector3[] { new Vector3(-0.5f, 0f, 0f), new Vector3(0.5f, 0f, 0f), new Vector3(0f, -0.5f, 0f), new Vector3(0f, 0.5f, 0f) }; override public int DrawGlyph(float x, float y, List vertList, List uvList, List uv2List, List colList) { topLeft.x = _char.minX; topLeft.y = _char.maxY; bottomRight.x = _char.maxX; if (_char.glyphWidth == 0) //zero width, space etc bottomRight.x = topLeft.x + _size / 2; bottomRight.y = _char.minY; if (keepCrisp) { topLeft /= UIContentScaler.scaleFactor; bottomRight /= UIContentScaler.scaleFactor; } if (_format.specialStyle == TextFormat.SpecialStyle.Subscript) y = y - Mathf.RoundToInt(_ascent * _scale * SupOffset); else if (_format.specialStyle == TextFormat.SpecialStyle.Superscript) y = y + Mathf.RoundToInt(_ascent * _scale * (1 / SupScale - 1 + SupOffset)); topLeft.x += x; topLeft.y += y; bottomRight.x += x; bottomRight.y += y; topRight.x = bottomRight.x; topRight.y = topLeft.y; bottomLeft.x = topLeft.x; bottomLeft.y = bottomRight.y; vertList.Add(bottomLeft); vertList.Add(topLeft); vertList.Add(topRight); vertList.Add(bottomRight); uvBottomLeft = _char.uvBottomLeft; uvTopLeft = _char.uvTopLeft; uvTopRight = _char.uvTopRight; uvBottomRight = _char.uvBottomRight; uvList.Add(uvBottomLeft); uvList.Add(uvTopLeft); uvList.Add(uvTopRight); uvList.Add(uvBottomRight); colList.Add(vertexColors[0]); colList.Add(vertexColors[1]); colList.Add(vertexColors[2]); colList.Add(vertexColors[3]); if (_boldVertice) { for (int b = 0; b < 4; b++) { Vector3 boldOffset = BOLD_OFFSET[b]; vertList.Add(bottomLeft + boldOffset); vertList.Add(topLeft + boldOffset); vertList.Add(topRight + boldOffset); vertList.Add(bottomRight + boldOffset); uvList.Add(uvBottomLeft); uvList.Add(uvTopLeft); uvList.Add(uvTopRight); uvList.Add(uvBottomRight); colList.Add(vertexColors[0]); colList.Add(vertexColors[1]); colList.Add(vertexColors[2]); colList.Add(vertexColors[3]); } return 20; } else return 4; } override public int DrawLine(float x, float y, float width, int fontSize, int type, List vertList, List uvList, List uv2List, List colList) { if (!_gotLineChar) { _gotLineChar = true; _font.RequestCharactersInTexture("_", 50, FontStyle.Normal); _font.GetCharacterInfo('_', out _lineChar, 50, FontStyle.Normal); } float thickness; float offset; thickness = Mathf.Max(1, fontSize / 16f); //guest underline size if (type == 0) offset = Mathf.RoundToInt(_lineChar.minY * (float)fontSize / 50 + thickness); else offset = Mathf.RoundToInt(_ascent * 0.4f * fontSize / _font.fontSize); if (thickness < 1) thickness = 1; topLeft.x = x; topLeft.y = y + offset; bottomRight.x = x + width; bottomRight.y = topLeft.y - thickness; topRight.x = bottomRight.x; topRight.y = topLeft.y; bottomLeft.x = topLeft.x; bottomLeft.y = bottomRight.y; vertList.Add(bottomLeft); vertList.Add(topLeft); vertList.Add(topRight); vertList.Add(bottomRight); uvBottomLeft = _lineChar.uvBottomLeft; uvTopLeft = _lineChar.uvTopLeft; uvTopRight = _lineChar.uvTopRight; uvBottomRight = _lineChar.uvBottomRight; //取中点的UV Vector2 u0; if (_lineChar.uvBottomLeft.x != _lineChar.uvBottomRight.x) u0.x = (_lineChar.uvBottomLeft.x + _lineChar.uvBottomRight.x) * 0.5f; else u0.x = (_lineChar.uvBottomLeft.x + _lineChar.uvTopLeft.x) * 0.5f; if (_lineChar.uvBottomLeft.y != _lineChar.uvTopLeft.y) u0.y = (_lineChar.uvBottomLeft.y + _lineChar.uvTopLeft.y) * 0.5f; else u0.y = (_lineChar.uvBottomLeft.y + _lineChar.uvBottomRight.y) * 0.5f; uvList.Add(u0); uvList.Add(u0); uvList.Add(u0); uvList.Add(u0); colList.Add(vertexColors[0]); colList.Add(vertexColors[1]); colList.Add(vertexColors[2]); colList.Add(vertexColors[3]); if (_boldVertice) { for (int b = 0; b < 4; b++) { Vector3 boldOffset = BOLD_OFFSET[b]; vertList.Add(bottomLeft + boldOffset); vertList.Add(topLeft + boldOffset); vertList.Add(topRight + boldOffset); vertList.Add(bottomRight + boldOffset); uvList.Add(u0); uvList.Add(u0); uvList.Add(u0); uvList.Add(u0); colList.Add(vertexColors[0]); colList.Add(vertexColors[1]); colList.Add(vertexColors[2]); colList.Add(vertexColors[3]); } return 20; } else return 4; } override public bool HasCharacter(char ch) { return _font.HasCharacter(ch); } override public int GetLineHeight(int size) { return Mathf.RoundToInt(_lineHeight * size / _font.fontSize); } void textureRebuildCallback(Font targetFont) { if (_font != targetFont) return; if (mainTexture == null || !Application.isPlaying) { mainTexture = new NTexture(_font.material.mainTexture); mainTexture.destroyMethod = DestroyMethod.None; } else mainTexture.Reload(_font.material.mainTexture, null); _gotLineChar = false; textRebuildFlag = true; version++; //Debug.Log("Font texture rebuild: " + name + "," + mainTexture.width + "," + mainTexture.height); } } }