123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701 |
- using System;
- using System.Collections.Generic;
- using System.Text;
- using UnityEngine;
- using FairyGUI.Utils;
- namespace FairyGUI
- {
-
-
-
- public class TextField : DisplayObject, IMeshFactory
- {
- VertAlignType _verticalAlign;
- TextFormat _textFormat;
- bool _input;
- string _text;
- AutoSizeType _autoSize;
- bool _wordWrap;
- bool _singleLine;
- bool _html;
- RTLSupport.DirectionType _textDirection;
- int _maxWidth;
- List<HtmlElement> _elements;
- List<LineInfo> _lines;
- List<CharPosition> _charPositions;
- BaseFont _font;
- float _textWidth;
- float _textHeight;
- bool _textChanged;
- float _yOffset;
- float _fontSizeScale;
- float _renderScale;
- int _fontVersion;
- string _parsedText;
- int _ellipsisCharIndex;
- RichTextField _richTextField;
- const int GUTTER_X = 2;
- const int GUTTER_Y = 2;
- const float IMAGE_BASELINE = 0.8f;
- const int ELLIPSIS_LENGTH = 2;
- static float[] STROKE_OFFSET = new float[]
- {
- -1, 0, 1, 0,
- 0, -1, 0, 1,
- -1, -1, 1, -1,
- -1, 1, 1, 1
- };
- static List<LineCharInfo> sLineChars = new List<LineCharInfo>();
- public TextField()
- {
- _flags |= Flags.TouchDisabled;
- _textFormat = new TextFormat();
- _fontSizeScale = 1;
- _renderScale = UIContentScaler.scaleFactor;
- _wordWrap = false;
- _text = string.Empty;
- _parsedText = string.Empty;
- _elements = new List<HtmlElement>(0);
- _lines = new List<LineInfo>(1);
- CreateGameObject("TextField");
- graphics = new NGraphics(gameObject);
- graphics.meshFactory = this;
- }
- internal void EnableRichSupport(RichTextField richTextField)
- {
- _richTextField = richTextField;
- if (richTextField is InputTextField)
- {
- _input = true;
- EnableCharPositionSupport();
- }
- }
- public void EnableCharPositionSupport()
- {
- if (_charPositions == null)
- {
- _charPositions = new List<CharPosition>();
- _textChanged = true;
- }
- }
-
-
-
- public TextFormat textFormat
- {
- get { return _textFormat; }
- set
- {
- _textFormat = value;
- ApplyFormat();
- }
- }
-
-
-
- public void ApplyFormat()
- {
- string fontName = _textFormat.font;
- if (string.IsNullOrEmpty(fontName))
- fontName = UIConfig.defaultFont;
- BaseFont newFont = FontManager.GetFont(fontName);
- if (_font != newFont)
- {
- _font = newFont;
- _fontVersion = _font.version;
- graphics.SetShaderAndTexture(_font.shader, _font.mainTexture);
- }
- if (!string.IsNullOrEmpty(_text))
- _textChanged = true;
- }
-
-
-
- public AlignType align
- {
- get { return _textFormat.align; }
- set
- {
- if (_textFormat.align != value)
- {
- _textFormat.align = value;
- if (!string.IsNullOrEmpty(_text))
- _textChanged = true;
- }
- }
- }
-
-
-
- public VertAlignType verticalAlign
- {
- get
- {
- return _verticalAlign;
- }
- set
- {
- if (_verticalAlign != value)
- {
- _verticalAlign = value;
- if (!_textChanged)
- ApplyVertAlign();
- }
- }
- }
-
-
-
- public string text
- {
- get { return _text; }
- set
- {
- if (_text == value && !_html)
- return;
- _text = value;
- _textChanged = true;
- _html = false;
- }
- }
-
-
-
- public string htmlText
- {
- get { return _text; }
- set
- {
- if (_text == value && _html)
- return;
- _text = value;
- _textChanged = true;
- _html = true;
- }
- }
- public string parsedText
- {
- get { return _parsedText; }
- }
-
-
-
- public AutoSizeType autoSize
- {
- get { return _autoSize; }
- set
- {
- if (_autoSize != value)
- {
- _autoSize = value;
- _textChanged = true;
- }
- }
- }
-
-
-
- public bool wordWrap
- {
- get { return _wordWrap; }
- set
- {
- if (_wordWrap != value)
- {
- _wordWrap = value;
- _textChanged = true;
- }
- }
- }
-
-
-
- public bool singleLine
- {
- get { return _singleLine; }
- set
- {
- if (_singleLine != value)
- {
- _singleLine = value;
- _textChanged = true;
- }
- }
- }
-
-
-
- public float stroke
- {
- get
- {
- return _textFormat.outline;
- }
- set
- {
- if (_textFormat.outline != value)
- {
- _textFormat.outline = value;
- graphics.SetMeshDirty();
- }
- }
- }
-
-
-
- public Color strokeColor
- {
- get
- {
- return _textFormat.outlineColor;
- }
- set
- {
- if (_textFormat.outlineColor != value)
- {
- _textFormat.outlineColor = value;
- graphics.SetMeshDirty();
- }
- }
- }
-
-
-
- public Vector2 shadowOffset
- {
- get
- {
- return _textFormat.shadowOffset;
- }
- set
- {
- _textFormat.shadowOffset = value;
- graphics.SetMeshDirty();
- }
- }
-
-
-
- public float textWidth
- {
- get
- {
- if (_textChanged)
- BuildLines();
- return _textWidth;
- }
- }
-
-
-
- public float textHeight
- {
- get
- {
- if (_textChanged)
- BuildLines();
- return _textHeight;
- }
- }
-
-
-
- public int maxWidth
- {
- get { return _maxWidth; }
- set
- {
- if (_maxWidth != value)
- {
- _maxWidth = value;
- _textChanged = true;
- }
- }
- }
-
-
-
- public List<HtmlElement> htmlElements
- {
- get
- {
- if (_textChanged)
- BuildLines();
- return _elements;
- }
- }
-
-
-
- public List<LineInfo> lines
- {
- get
- {
- if (_textChanged)
- BuildLines();
- return _lines;
- }
- }
-
-
-
- public List<CharPosition> charPositions
- {
- get
- {
- if (_textChanged)
- BuildLines();
- graphics.UpdateMesh();
- return _charPositions;
- }
- }
-
-
-
- public RichTextField richTextField
- {
- get { return _richTextField; }
- }
-
-
-
- public bool Redraw()
- {
- if (_font == null)
- {
- _font = FontManager.GetFont(UIConfig.defaultFont);
- graphics.SetShaderAndTexture(_font.shader, _font.mainTexture);
- _fontVersion = _font.version;
- _textChanged = true;
- }
- if (_font.keepCrisp && _renderScale != UIContentScaler.scaleFactor)
- _textChanged = true;
- if (_font.version != _fontVersion)
- {
- _fontVersion = _font.version;
- if (_font.mainTexture != graphics.texture)
- {
- graphics.SetShaderAndTexture(_font.shader, _font.mainTexture);
- InvalidateBatchingState();
- }
- _textChanged = true;
- }
- if (_textChanged)
- BuildLines();
- return graphics.UpdateMesh();
- }
-
-
-
- public bool HasCharacter(char ch)
- {
- return _font.HasCharacter(ch);
- }
-
-
-
-
-
-
-
-
-
- public void GetLinesShape(int startLine, float startCharX, int endLine, float endCharX,
- bool clipped,
- List<Rect> resultRects)
- {
- LineInfo line1 = _lines[startLine];
- LineInfo line2 = _lines[endLine];
- bool leftAlign = _textFormat.align == AlignType.Left;
- if (startLine == endLine)
- {
- Rect r = Rect.MinMaxRect(startCharX, line1.y, endCharX, line1.y + line1.height);
- if (clipped)
- resultRects.Add(ToolSet.Intersection(ref r, ref _contentRect));
- else
- resultRects.Add(r);
- }
- else if (startLine == endLine - 1)
- {
- Rect r = Rect.MinMaxRect(startCharX, line1.y, leftAlign ? (GUTTER_X + line1.width) : _contentRect.xMax, line1.y + line1.height);
- if (clipped)
- resultRects.Add(ToolSet.Intersection(ref r, ref _contentRect));
- else
- resultRects.Add(r);
- r = Rect.MinMaxRect(GUTTER_X, line1.y + line1.height, endCharX, line2.y + line2.height);
- if (clipped)
- resultRects.Add(ToolSet.Intersection(ref r, ref _contentRect));
- else
- resultRects.Add(r);
- }
- else
- {
- Rect r = Rect.MinMaxRect(startCharX, line1.y, leftAlign ? (GUTTER_X + line1.width) : _contentRect.xMax, line1.y + line1.height);
- if (clipped)
- resultRects.Add(ToolSet.Intersection(ref r, ref _contentRect));
- else
- resultRects.Add(r);
- for (int i = startLine + 1; i < endLine; i++)
- {
- LineInfo line = _lines[i];
- r = Rect.MinMaxRect(GUTTER_X, r.yMax, leftAlign ? (GUTTER_X + line.width) : _contentRect.xMax, line.y + line.height);
- if (clipped)
- resultRects.Add(ToolSet.Intersection(ref r, ref _contentRect));
- else
- resultRects.Add(r);
- }
- r = Rect.MinMaxRect(GUTTER_X, r.yMax, endCharX, line2.y + line2.height);
- if (clipped)
- resultRects.Add(ToolSet.Intersection(ref r, ref _contentRect));
- else
- resultRects.Add(r);
- }
- }
- override protected void OnSizeChanged()
- {
- if ((_flags & Flags.UpdatingSize) == 0)
- {
- if (_autoSize == AutoSizeType.Shrink || _autoSize == AutoSizeType.Ellipsis || _wordWrap && (_flags & Flags.WidthChanged) != 0)
- _textChanged = true;
- else if (_autoSize != AutoSizeType.None)
- graphics.SetMeshDirty();
- if (_verticalAlign != VertAlignType.Top)
- ApplyVertAlign();
- }
- base.OnSizeChanged();
- }
- public override void EnsureSizeCorrect()
- {
- if (_textChanged && _autoSize != AutoSizeType.None)
- BuildLines();
- }
- public override void Update(UpdateContext context)
- {
- if (_richTextField == null)
- Redraw();
- base.Update(context);
- }
-
-
-
- void RequestText()
- {
- if (!_html)
- {
- _font.SetFormat(_textFormat, _fontSizeScale);
- _font.PrepareCharacters(_parsedText);
- if (_autoSize == AutoSizeType.Ellipsis)
- _font.PrepareCharacters("…");
- }
- else
- {
- int count = _elements.Count;
- for (int i = 0; i < count; i++)
- {
- HtmlElement element = _elements[i];
- if (element.type == HtmlElementType.Text)
- {
- _font.SetFormat(element.format, _fontSizeScale);
- _font.PrepareCharacters(element.text);
- if (_autoSize == AutoSizeType.Ellipsis)
- _font.PrepareCharacters("…");
- }
- }
- }
- }
- void BuildLines()
- {
- if (_font == null)
- {
- _font = FontManager.GetFont(UIConfig.defaultFont);
- _fontVersion = _font.version;
- graphics.SetShaderAndTexture(_font.shader, _font.mainTexture);
- }
- _textChanged = false;
- graphics.SetMeshDirty();
- _renderScale = UIContentScaler.scaleFactor;
- _fontSizeScale = 1;
- _ellipsisCharIndex = -1;
- Cleanup();
- if (_text.Length == 0)
- {
- LineInfo emptyLine = LineInfo.Borrow();
- emptyLine.width = 0;
- emptyLine.height = _font.GetLineHeight(_textFormat.size);
- emptyLine.charIndex = emptyLine.charCount = 0;
- emptyLine.y = emptyLine.y2 = GUTTER_Y;
- _lines.Add(emptyLine);
- _textWidth = _textHeight = 0;
- }
- else
- {
- ParseText();
- BuildLines2();
- if (_autoSize == AutoSizeType.Shrink)
- DoShrink();
- }
- if (_autoSize == AutoSizeType.Both)
- {
- _flags |= Flags.UpdatingSize;
- if (_richTextField != null)
- {
- if (_input)
- {
- float w = Mathf.Max(_textFormat.size, _textWidth);
- float h = Mathf.Max(_font.GetLineHeight(_textFormat.size) + GUTTER_Y * 2, _textHeight);
- _richTextField.SetSize(w, h);
- }
- else
- _richTextField.SetSize(_textWidth, _textHeight);
- }
- else
- SetSize(_textWidth, _textHeight);
- InvalidateBatchingState();
- _flags &= ~Flags.UpdatingSize;
- }
- else if (_autoSize == AutoSizeType.Height)
- {
- _flags |= Flags.UpdatingSize;
- if (_richTextField != null)
- {
- if (_input)
- _richTextField.height = Mathf.Max(_font.GetLineHeight(_textFormat.size) + GUTTER_Y * 2, _textHeight);
- else
- _richTextField.height = _textHeight;
- }
- else
- this.height = _textHeight;
- InvalidateBatchingState();
- _flags &= ~Flags.UpdatingSize;
- }
- _yOffset = 0;
- ApplyVertAlign();
- }
- void ParseText()
- {
- #if RTL_TEXT_SUPPORT
- _textDirection = RTLSupport.DetectTextDirection(_text);
- #endif
- if (_html)
- {
- HtmlParser.inst.Parse(_text, _textFormat, _elements,
- _richTextField != null ? _richTextField.htmlParseOptions : null);
- _parsedText = string.Empty;
- }
- else
- _parsedText = _text;
- int elementCount = _elements.Count;
- if (elementCount == 0)
- {
- if (_textDirection != RTLSupport.DirectionType.UNKNOW)
- _parsedText = RTLSupport.DoMapping(_parsedText);
- bool flag = _input || _richTextField != null && _richTextField.emojies != null;
- if (!flag)
- {
-
- int cnt = _parsedText.Length;
- for (int i = 0; i < cnt; i++)
- {
- char ch = _parsedText[i];
- if (ch == '\r' || char.IsHighSurrogate(ch))
- {
- flag = true;
- break;
- }
- }
- }
- if (flag)
- {
- StringBuilder buffer = new StringBuilder();
- ParseText(buffer, _parsedText, -1);
- elementCount = _elements.Count;
- _parsedText = buffer.ToString();
- }
- }
- else
- {
- StringBuilder buffer = new StringBuilder();
- int i = 0;
- while (i < elementCount)
- {
- HtmlElement element = _elements[i];
- element.charIndex = buffer.Length;
- if (element.type == HtmlElementType.Text)
- {
- if (_textDirection != RTLSupport.DirectionType.UNKNOW)
- element.text = RTLSupport.DoMapping(element.text);
- i = ParseText(buffer, element.text, i);
- elementCount = _elements.Count;
- }
- else if (element.isEntity)
- buffer.Append(' ');
- i++;
- }
- _parsedText = buffer.ToString();
- #if RTL_TEXT_SUPPORT
-
- _textDirection = RTLSupport.DetectTextDirection(_parsedText);
- #endif
- }
- }
- void BuildLines2()
- {
- float letterSpacing = _textFormat.letterSpacing * _fontSizeScale;
- float lineSpacing = (_textFormat.lineSpacing - 1) * _fontSizeScale;
- float rectWidth = _contentRect.width - GUTTER_X * 2;
- float rectHeight = _contentRect.height > 0 ? Mathf.Max(_contentRect.height, _font.GetLineHeight(_textFormat.size)) : 0;
- float glyphWidth = 0, glyphHeight = 0, baseline = 0;
- short wordLen = 0;
- bool wordPossible = false;
- float posx = 0;
- bool checkEdge = _autoSize == AutoSizeType.Ellipsis;
- TextFormat format = _textFormat;
- _font.SetFormat(format, _fontSizeScale);
- bool wrap = _wordWrap && !_singleLine;
- if (_maxWidth > 0)
- {
- wrap = true;
- rectWidth = _maxWidth - GUTTER_X * 2;
- }
- _textWidth = _textHeight = 0;
- RequestText();
- int elementCount = _elements.Count;
- int elementIndex = 0;
- HtmlElement element = null;
- if (elementCount > 0)
- element = _elements[elementIndex];
- int textLength = _parsedText.Length;
- LineInfo line = LineInfo.Borrow();
- _lines.Add(line);
- line.y = line.y2 = GUTTER_Y;
- sLineChars.Clear();
- for (int charIndex = 0; charIndex < textLength; charIndex++)
- {
- char ch = _parsedText[charIndex];
- glyphWidth = glyphHeight = baseline = 0;
- while (element != null && element.charIndex == charIndex)
- {
- if (element.type == HtmlElementType.Text)
- {
- format = element.format;
- _font.SetFormat(format, _fontSizeScale);
- }
- else
- {
- IHtmlObject htmlObject = element.htmlObject;
- if (_richTextField != null && htmlObject == null)
- {
- element.space = (int)(rectWidth - line.width - 4);
- htmlObject = _richTextField.htmlPageContext.CreateObject(_richTextField, element);
- element.htmlObject = htmlObject;
- }
- if (htmlObject != null)
- {
- glyphWidth = htmlObject.width + 2;
- glyphHeight = htmlObject.height;
- baseline = glyphHeight * IMAGE_BASELINE;
- }
- if (element.isEntity)
- ch = '\0';
- }
- elementIndex++;
- if (elementIndex < elementCount)
- element = _elements[elementIndex];
- else
- element = null;
- }
- if (ch == '\0' || ch == '\n')
- {
- wordPossible = false;
- }
- else if (_font.GetGlyph(ch == '\t' ? ' ' : ch, out glyphWidth, out glyphHeight, out baseline))
- {
- if (ch == '\t')
- glyphWidth *= 4;
- if (wordPossible)
- {
- if (char.IsWhiteSpace(ch))
- {
- wordLen = 0;
- }
- else if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z'
- || ch >= '0' && ch <= '9'
- || ch == '.' || ch == '"' || ch == '\''
- || format.specialStyle == TextFormat.SpecialStyle.Subscript
- || format.specialStyle == TextFormat.SpecialStyle.Superscript
- || _textDirection != RTLSupport.DirectionType.UNKNOW && RTLSupport.IsArabicLetter(ch))
- {
- wordLen++;
- }
- else
- wordPossible = false;
- }
- else if (char.IsWhiteSpace(ch))
- {
- wordLen = 0;
- wordPossible = true;
- }
- else if (format.specialStyle == TextFormat.SpecialStyle.Subscript
- || format.specialStyle == TextFormat.SpecialStyle.Superscript)
- {
- if (sLineChars.Count > 0)
- {
- wordLen = 2;
- wordPossible = true;
- }
- }
- else
- wordPossible = false;
- }
- else
- wordPossible = false;
- sLineChars.Add(new LineCharInfo() { width = glyphWidth, height = glyphHeight, baseline = baseline });
- if (glyphWidth != 0)
- {
- if (posx != 0)
- posx += letterSpacing;
- posx += glyphWidth;
- }
- if (ch == '\n' && !_singleLine)
- {
- UpdateLineInfo(line, letterSpacing, sLineChars.Count);
- LineInfo newLine = LineInfo.Borrow();
- _lines.Add(newLine);
- newLine.y = line.y + (line.height + lineSpacing);
- if (newLine.y < GUTTER_Y)
- newLine.y = GUTTER_Y;
- newLine.y2 = newLine.y;
- newLine.charIndex = line.charIndex + line.charCount;
- if (checkEdge && line.y + line.height < rectHeight)
- _ellipsisCharIndex = line.charIndex + Math.Max(0, line.charCount - ELLIPSIS_LENGTH);
- sLineChars.Clear();
- wordPossible = false;
- posx = 0;
- line = newLine;
- }
- else if (posx > rectWidth)
- {
- if (wrap)
- {
- int lineCharCount = sLineChars.Count;
- int toMoveChars;
- if (wordPossible && wordLen < 20 && lineCharCount > 2)
- {
- toMoveChars = wordLen;
-
- UpdateLineInfo(line, letterSpacing, lineCharCount - (toMoveChars + 1));
- line.charCount++;
- }
- else
- {
- toMoveChars = lineCharCount > 1 ? 1 : 0;
- UpdateLineInfo(line, letterSpacing, lineCharCount - toMoveChars);
- }
- LineInfo newLine = LineInfo.Borrow();
- _lines.Add(newLine);
- newLine.y = line.y + (line.height + lineSpacing);
- if (newLine.y < GUTTER_Y)
- newLine.y = GUTTER_Y;
- newLine.y2 = newLine.y;
- newLine.charIndex = line.charIndex + line.charCount;
- posx = 0;
- if (toMoveChars != 0)
- {
- for (int i = line.charCount; i < lineCharCount; i++)
- {
- LineCharInfo ci = sLineChars[i];
- if (posx != 0)
- posx += letterSpacing;
- posx += ci.width;
- }
- sLineChars.RemoveRange(0, line.charCount);
- }
- else
- sLineChars.Clear();
- if (checkEdge && line.y + line.height < rectHeight)
- _ellipsisCharIndex = line.charIndex + Math.Max(0, line.charCount - ELLIPSIS_LENGTH);
- wordPossible = false;
- line = newLine;
- }
- else if (checkEdge && _ellipsisCharIndex == -1)
- _ellipsisCharIndex = line.charIndex + Math.Max(0, line.charCount - ELLIPSIS_LENGTH);
- }
- }
- UpdateLineInfo(line, letterSpacing, sLineChars.Count);
- if (_textWidth > 0)
- _textWidth += GUTTER_X * 2;
- _textHeight = line.y + line.height + GUTTER_Y;
- if (checkEdge && _textWidth <= _contentRect.width && _textHeight <= _contentRect.height + GUTTER_Y)
- _ellipsisCharIndex = -1;
- _textWidth = Mathf.RoundToInt(_textWidth);
- _textHeight = Mathf.RoundToInt(_textHeight);
- }
- void UpdateLineInfo(LineInfo line, float letterSpacing, int cnt)
- {
- for (int i = 0; i < cnt; i++)
- {
- LineCharInfo ci = sLineChars[i];
- if (ci.baseline > line.baseline)
- {
- line.height += (ci.baseline - line.baseline);
- line.baseline = ci.baseline;
- }
- if (ci.height - ci.baseline > line.height - line.baseline)
- line.height += (ci.height - ci.baseline - (line.height - line.baseline));
- if (ci.width > 0)
- {
- if (line.width != 0)
- line.width += letterSpacing;
- line.width += ci.width;
- }
- }
- if (line.height == 0)
- {
- if (_lines.Count == 1)
- line.height = _textFormat.size;
- else
- line.height = _lines[_lines.Count - 2].height;
- }
- if (line.width > _textWidth)
- _textWidth = line.width;
- line.charCount = (short)cnt;
- }
- void DoShrink()
- {
- if (_lines.Count > 1 && _textHeight > _contentRect.height)
- {
-
- int low = 0;
- int high = _textFormat.size;
-
- _fontSizeScale = Mathf.Sqrt(_contentRect.height / _textHeight);
- int cur = Mathf.FloorToInt(_fontSizeScale * _textFormat.size);
- while (true)
- {
- LineInfo.Return(_lines);
- BuildLines2();
- if (_textWidth > _contentRect.width || _textHeight > _contentRect.height)
- high = cur;
- else
- low = cur;
- if (high - low > 1 || high != low && cur == high)
- {
- cur = low + (high - low) / 2;
- _fontSizeScale = (float)cur / _textFormat.size;
- }
- else
- break;
- }
- }
- else if (_textWidth > _contentRect.width)
- {
- _fontSizeScale = _contentRect.width / _textWidth;
- LineInfo.Return(_lines);
- BuildLines2();
- if (_textWidth > _contentRect.width)
- {
- int size = Mathf.FloorToInt(_textFormat.size * _fontSizeScale);
- size--;
- _fontSizeScale = (float)size / _textFormat.size;
- LineInfo.Return(_lines);
- BuildLines2();
- }
- }
- }
- int ParseText(StringBuilder buffer, string source, int elementIndex)
- {
- int textLength = source.Length;
- int j = 0;
- int appendPos = 0;
- bool hasEmojies = _richTextField != null && _richTextField.emojies != null;
- while (j < textLength)
- {
- char ch = source[j];
- if (ch == '\r')
- {
- buffer.Append(source, appendPos, j - appendPos);
- if (j != textLength - 1 && source[j + 1] == '\n')
- j++;
- appendPos = j + 1;
- buffer.Append('\n');
- }
- else
- {
- bool highSurrogate = char.IsHighSurrogate(ch);
- if (hasEmojies)
- {
- uint emojiKey = 0;
- Emoji emoji;
- if (highSurrogate)
- emojiKey = ((uint)source[j + 1] & 0x03FF) + ((((uint)ch & 0x03FF) + 0x40) << 10);
- else
- emojiKey = ch;
- if (_richTextField.emojies.TryGetValue(emojiKey, out emoji))
- {
- HtmlElement imageElement = HtmlElement.GetElement(HtmlElementType.Image);
- imageElement.Set("src", emoji.url);
- if (emoji.width != 0)
- imageElement.Set("width", emoji.width);
- if (emoji.height != 0)
- imageElement.Set("height", emoji.height);
- if (highSurrogate)
- imageElement.text = source.Substring(j, 2);
- else
- imageElement.text = source.Substring(j, 1);
- imageElement.format.align = _textFormat.align;
- _elements.Insert(++elementIndex, imageElement);
- buffer.Append(source, appendPos, j - appendPos);
- appendPos = j;
- imageElement.charIndex = buffer.Length;
- }
- }
- if (highSurrogate)
- {
- buffer.Append(source, appendPos, j - appendPos);
- appendPos = j + 2;
- j++;
- buffer.Append(' ');
- }
- }
- j++;
- }
- if (appendPos < textLength)
- buffer.Append(source, appendPos, j - appendPos);
- return elementIndex;
- }
- public void OnPopulateMesh(VertexBuffer vb)
- {
- if (_textWidth == 0 && _lines.Count == 1)
- {
- if (_charPositions != null)
- {
- _charPositions.Clear();
- _charPositions.Add(new CharPosition());
- }
- if (_richTextField != null)
- _richTextField.RefreshObjects();
- return;
- }
- float letterSpacing = _textFormat.letterSpacing * _fontSizeScale;
- TextFormat format = _textFormat;
- _font.SetFormat(format, _fontSizeScale);
- _font.UpdateGraphics(graphics);
- float rectWidth = _contentRect.width > 0 ? (_contentRect.width - GUTTER_X * 2) : 0;
- float rectHeight = _contentRect.height > 0 ? Mathf.Max(_contentRect.height, _font.GetLineHeight(format.size)) : 0;
- if (_charPositions != null)
- _charPositions.Clear();
- List<Vector3> vertList = vb.vertices;
- List<Vector2> uvList = vb.uvs;
- List<Vector2> uv2List = vb.uvs2;
- List<Color32> colList = vb.colors;
- HtmlLink currentLink = null;
- float linkStartX = 0;
- int linkStartLine = 0;
- float posx = 0;
- float indent_x;
- bool clipping = !_input && (_autoSize == AutoSizeType.None || _autoSize == AutoSizeType.Ellipsis);
- bool lineClipped;
- AlignType lineAlign;
- float glyphWidth, glyphHeight, baseline;
- short vertCount;
- float underlineStart;
- float strikethroughStart;
- int minFontSize;
- int maxFontSize;
- string rtlLine = null;
- int elementIndex = 0;
- int elementCount = _elements.Count;
- HtmlElement element = null;
- if (elementCount > 0)
- element = _elements[elementIndex];
- int lineCount = _lines.Count;
- for (int i = 0; i < lineCount; ++i)
- {
- LineInfo line = _lines[i];
- if (line.charCount == 0)
- continue;
- lineClipped = clipping && i != 0 && line.y + line.height > rectHeight;
- lineAlign = format.align;
- if (element != null && element.charIndex == line.charIndex)
- lineAlign = element.format.align;
- else
- lineAlign = format.align;
- if (_textDirection == RTLSupport.DirectionType.RTL)
- {
- if (lineAlign == AlignType.Center)
- indent_x = (int)((rectWidth + line.width) / 2);
- else if (lineAlign == AlignType.Right)
- indent_x = rectWidth;
- else
- indent_x = line.width + GUTTER_X * 2;
- if (indent_x > rectWidth)
- indent_x = rectWidth;
- posx = indent_x - GUTTER_X;
- }
- else
- {
- if (lineAlign == AlignType.Center)
- indent_x = (int)((rectWidth - line.width) / 2);
- else if (lineAlign == AlignType.Right)
- indent_x = rectWidth - line.width;
- else
- indent_x = 0;
- if (indent_x < 0)
- indent_x = 0;
- posx = GUTTER_X + indent_x;
- }
- int lineCharCount = line.charCount;
- underlineStart = posx;
- strikethroughStart = posx;
- minFontSize = maxFontSize = format.size;
- if (_textDirection != RTLSupport.DirectionType.UNKNOW)
- {
- rtlLine = _parsedText.Substring(line.charIndex, lineCharCount);
- if (_textDirection == RTLSupport.DirectionType.RTL)
- rtlLine = RTLSupport.ConvertLineR(rtlLine);
- else
- rtlLine = RTLSupport.ConvertLineL(rtlLine);
- lineCharCount = rtlLine.Length;
- }
- for (int j = 0; j < lineCharCount; j++)
- {
- int charIndex = line.charIndex + j;
- char ch = rtlLine != null ? rtlLine[j] : _parsedText[charIndex];
- bool isEllipsis = charIndex == _ellipsisCharIndex;
- while (element != null && charIndex == element.charIndex)
- {
- if (element.type == HtmlElementType.Text)
- {
- vertCount = 0;
- if (format.underline != element.format.underline)
- {
- if (format.underline)
- {
- if (!lineClipped)
- {
- float lineWidth;
- if (_textDirection == RTLSupport.DirectionType.UNKNOW)
- lineWidth = (clipping ? Mathf.Clamp(posx, GUTTER_X, GUTTER_X + rectWidth) : posx) - underlineStart;
- else
- lineWidth = underlineStart - (clipping ? Mathf.Clamp(posx, GUTTER_X, GUTTER_X + rectWidth) : posx);
- if (lineWidth > 0)
- vertCount += (short)_font.DrawLine(underlineStart < posx ? underlineStart : posx, -(line.y + line.baseline), lineWidth,
- maxFontSize, 0, vertList, uvList, uv2List, colList);
- }
- maxFontSize = 0;
- }
- else
- underlineStart = posx;
- }
- if (format.strikethrough != element.format.strikethrough)
- {
- if (format.strikethrough)
- {
- if (!lineClipped)
- {
- float lineWidth;
- if (_textDirection == RTLSupport.DirectionType.UNKNOW)
- lineWidth = (clipping ? Mathf.Clamp(posx, GUTTER_X, GUTTER_X + rectWidth) : posx) - strikethroughStart;
- else
- lineWidth = strikethroughStart - (clipping ? Mathf.Clamp(posx, GUTTER_X, GUTTER_X + rectWidth) : posx);
- if (lineWidth > 0)
- vertCount += (short)_font.DrawLine(strikethroughStart < posx ? strikethroughStart : posx, -(line.y + line.baseline), lineWidth,
- minFontSize, 1, vertList, uvList, uv2List, colList);
- }
- minFontSize = int.MaxValue;
- }
- else
- strikethroughStart = posx;
- }
- if (vertCount > 0 && _charPositions != null)
- {
- CharPosition cp = _charPositions[_charPositions.Count - 1];
- cp.vertCount += vertCount;
- _charPositions[_charPositions.Count - 1] = cp;
- }
- format = element.format;
- minFontSize = Math.Min(minFontSize, format.size);
- maxFontSize = Math.Max(maxFontSize, format.size);
- _font.SetFormat(format, _fontSizeScale);
- }
- else if (element.type == HtmlElementType.Link)
- {
- currentLink = (HtmlLink)element.htmlObject;
- if (currentLink != null)
- {
- element.position = Vector2.zero;
- currentLink.SetPosition(0, 0);
- linkStartX = posx;
- linkStartLine = i;
- }
- }
- else if (element.type == HtmlElementType.LinkEnd)
- {
- if (currentLink != null)
- {
- currentLink.SetArea(linkStartLine, linkStartX, i, posx);
- currentLink = null;
- }
- }
- else
- {
- IHtmlObject htmlObj = element.htmlObject;
- if (htmlObj != null)
- {
- if (_textDirection == RTLSupport.DirectionType.RTL)
- posx -= htmlObj.width - 2;
- if (_charPositions != null)
- {
- CharPosition cp = new CharPosition();
- cp.lineIndex = (short)i;
- cp.charIndex = _charPositions.Count;
- cp.imgIndex = (short)(elementIndex + 1);
- cp.offsetX = posx;
- cp.width = (short)htmlObj.width;
- _charPositions.Add(cp);
- }
- if (isEllipsis || lineClipped || clipping && (posx < GUTTER_X || posx > GUTTER_X && posx + htmlObj.width > _contentRect.width - GUTTER_X))
- element.status |= 1;
- else
- element.status &= 254;
- element.position = new Vector2(posx + 1, line.y + line.baseline - htmlObj.height * IMAGE_BASELINE);
- htmlObj.SetPosition(element.position.x, element.position.y);
- if (_textDirection == RTLSupport.DirectionType.RTL)
- posx -= letterSpacing;
- else
- posx += htmlObj.width + letterSpacing + 2;
- }
- }
- if (element.isEntity)
- ch = '\0';
- elementIndex++;
- if (elementIndex < elementCount)
- element = _elements[elementIndex];
- else
- element = null;
- }
- if (isEllipsis)
- ch = '…';
- else if (ch == '\0')
- continue;
- if (_font.GetGlyph(ch == '\t' ? ' ' : ch, out glyphWidth, out glyphHeight, out baseline))
- {
- if (ch == '\t')
- glyphWidth *= 4;
- if (!isEllipsis)
- {
- if (_textDirection == RTLSupport.DirectionType.RTL)
- {
- if (lineClipped || clipping && (rectWidth < 7 || posx != (indent_x - GUTTER_X)) && posx < GUTTER_X - 0.5f)
- {
- posx -= (letterSpacing + glyphWidth);
- continue;
- }
- posx -= glyphWidth;
- }
- else
- {
- if (lineClipped || clipping && (rectWidth < 7 || posx != (GUTTER_X + indent_x)) && posx + glyphWidth > _contentRect.width - GUTTER_X + 0.5f)
- {
- posx += letterSpacing + glyphWidth;
- continue;
- }
- }
- }
- vertCount = (short)_font.DrawGlyph(posx, -(line.y + line.baseline), vertList, uvList, uv2List, colList);
- if (_charPositions != null)
- {
- CharPosition cp = new CharPosition();
- cp.lineIndex = (short)i;
- cp.charIndex = _charPositions.Count;
- cp.vertCount = vertCount;
- cp.offsetX = posx;
- cp.width = (short)glyphWidth;
- _charPositions.Add(cp);
- }
- if (_textDirection == RTLSupport.DirectionType.RTL)
- posx -= letterSpacing;
- else
- posx += letterSpacing + glyphWidth;
- }
- else
- {
- if (_charPositions != null)
- {
- CharPosition cp = new CharPosition();
- cp.lineIndex = (short)i;
- cp.charIndex = _charPositions.Count;
- cp.offsetX = posx;
- _charPositions.Add(cp);
- }
- if (_textDirection == RTLSupport.DirectionType.RTL)
- posx -= letterSpacing;
- else
- posx += letterSpacing;
- }
- if (isEllipsis)
- lineClipped = true;
- }
- if (!lineClipped)
- {
- vertCount = 0;
- if (format.underline)
- {
- float lineWidth;
- if (_textDirection == RTLSupport.DirectionType.UNKNOW)
- lineWidth = (clipping ? Mathf.Clamp(posx, GUTTER_X, GUTTER_X + rectWidth) : posx) - underlineStart;
- else
- lineWidth = underlineStart - (clipping ? Mathf.Clamp(posx, GUTTER_X, GUTTER_X + rectWidth) : posx);
- if (lineWidth > 0)
- vertCount += (short)_font.DrawLine(underlineStart < posx ? underlineStart : posx, -(line.y + line.baseline), lineWidth,
- maxFontSize, 0, vertList, uvList, uv2List, colList);
- }
- if (format.strikethrough)
- {
- float lineWidth;
- if (_textDirection == RTLSupport.DirectionType.UNKNOW)
- lineWidth = (clipping ? Mathf.Clamp(posx, GUTTER_X, GUTTER_X + rectWidth) : posx) - strikethroughStart;
- else
- lineWidth = strikethroughStart - (clipping ? Mathf.Clamp(posx, GUTTER_X, GUTTER_X + rectWidth) : posx);
- if (lineWidth > 0)
- vertCount += (short)_font.DrawLine(strikethroughStart < posx ? strikethroughStart : posx, -(line.y + line.baseline), lineWidth,
- minFontSize, 1, vertList, uvList, uv2List, colList);
- }
- if (vertCount > 0 && _charPositions != null)
- {
- CharPosition cp = _charPositions[_charPositions.Count - 1];
- cp.vertCount += vertCount;
- _charPositions[_charPositions.Count - 1] = cp;
- }
- }
- }
- if (element != null && element.type == HtmlElementType.LinkEnd && currentLink != null)
- currentLink.SetArea(linkStartLine, linkStartX, lineCount - 1, posx);
- if (_charPositions != null)
- {
- CharPosition cp = new CharPosition();
- cp.lineIndex = (short)(lineCount - 1);
- cp.charIndex = _charPositions.Count;
- cp.offsetX = posx;
- _charPositions.Add(cp);
- }
- int count = vertList.Count;
- if (count > 65000)
- {
- Debug.LogWarning("Text is too large. A mesh may not have more than 65000 vertices.");
- vertList.RemoveRange(65000, count - 65000);
- colList.RemoveRange(65000, count - 65000);
- uvList.RemoveRange(65000, count - 65000);
- if (uv2List.Count > 0)
- uv2List.RemoveRange(65000, count - 65000);
- count = 65000;
- }
- if (_font.customOutline)
- {
- bool hasShadow = _textFormat.shadowOffset.x != 0 || _textFormat.shadowOffset.y != 0;
- int allocCount = count;
- int drawDirs = 0;
- if (_textFormat.outline != 0)
- {
- drawDirs = UIConfig.enhancedTextOutlineEffect ? 8 : 4;
- allocCount += count * drawDirs;
- }
- if (hasShadow)
- allocCount += count;
- if (allocCount > 65000)
- {
- Debug.LogWarning("Text is too large. Outline/shadow effect cannot be completed.");
- allocCount = count;
- }
- if (allocCount != count)
- {
- VertexBuffer vb2 = VertexBuffer.Begin();
- List<Vector3> vertList2 = vb2.vertices;
- List<Color32> colList2 = vb2.colors;
- Color32 col = _textFormat.outlineColor;
- float outline = _textFormat.outline;
- if (outline != 0)
- {
- for (int j = 0; j < drawDirs; j++)
- {
- for (int i = 0; i < count; i++)
- {
- Vector3 vert = vertList[i];
- vertList2.Add(new Vector3(vert.x + STROKE_OFFSET[j * 2] * outline, vert.y + STROKE_OFFSET[j * 2 + 1] * outline, 0));
- colList2.Add(col);
- }
- vb2.uvs.AddRange(uvList);
- if (uv2List.Count > 0)
- vb2.uvs2.AddRange(uv2List);
- }
- }
- if (hasShadow)
- {
- col = _textFormat.shadowColor;
- Vector2 offset = _textFormat.shadowOffset;
- for (int i = 0; i < count; i++)
- {
- Vector3 vert = vertList[i];
- vertList2.Add(new Vector3(vert.x + offset.x, vert.y - offset.y, 0));
- colList2.Add(col);
- }
- vb2.uvs.AddRange(uvList);
- if (uv2List.Count > 0)
- vb2.uvs2.AddRange(uv2List);
- }
- vb.Insert(vb2);
- vb2.End();
- }
- }
- vb.AddTriangles();
- if (_richTextField != null)
- _richTextField.RefreshObjects();
- }
- void Cleanup()
- {
- if (_richTextField != null)
- _richTextField.CleanupObjects();
- HtmlElement.ReturnElements(_elements);
- LineInfo.Return(_lines);
- _textWidth = 0;
- _textHeight = 0;
- _parsedText = string.Empty;
- _textDirection = RTLSupport.DirectionType.UNKNOW;
- if (_charPositions != null)
- _charPositions.Clear();
- }
- void ApplyVertAlign()
- {
- float oldOffset = _yOffset;
- if (_autoSize == AutoSizeType.Both || _autoSize == AutoSizeType.Height
- || _verticalAlign == VertAlignType.Top)
- _yOffset = 0;
- else
- {
- float dh;
- if (_textHeight == 0 && _lines.Count > 0)
- dh = _contentRect.height - _lines[0].height;
- else
- dh = _contentRect.height - _textHeight;
- if (dh < 0)
- dh = 0;
- if (_verticalAlign == VertAlignType.Middle)
- _yOffset = (int)(dh / 2);
- else
- _yOffset = dh;
- }
- if (oldOffset != _yOffset)
- {
- int cnt = _lines.Count;
- for (int i = 0; i < cnt; i++)
- _lines[i].y = _lines[i].y2 + _yOffset;
- graphics.SetMeshDirty();
- }
- }
-
-
-
- public class LineInfo
- {
-
-
-
- public float width;
-
-
-
- public float height;
-
-
-
- public float baseline;
-
-
-
- public int charIndex;
-
-
-
- public short charCount;
-
-
-
- public float y;
-
-
-
- internal float y2;
- static Stack<LineInfo> pool = new Stack<LineInfo>();
-
-
-
-
- public static LineInfo Borrow()
- {
- if (pool.Count > 0)
- {
- LineInfo ret = pool.Pop();
- ret.width = ret.height = ret.baseline = 0;
- ret.y = ret.y2 = 0;
- ret.charIndex = ret.charCount = 0;
- return ret;
- }
- else
- return new LineInfo();
- }
-
-
-
-
- public static void Return(LineInfo value)
- {
- pool.Push(value);
- }
-
-
-
-
- public static void Return(List<LineInfo> values)
- {
- int cnt = values.Count;
- for (int i = 0; i < cnt; i++)
- pool.Push(values[i]);
- values.Clear();
- }
- }
-
-
-
- public struct LineCharInfo
- {
- public float width;
- public float height;
- public float baseline;
- }
-
-
-
- public struct CharPosition
- {
-
-
-
- public int charIndex;
-
-
-
- public short lineIndex;
-
-
-
- public float offsetX;
-
-
-
- public short vertCount;
-
-
-
- public short width;
-
-
-
- public short imgIndex;
- }
- }
- }
|