TextField.cs 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using UnityEngine;
  5. using FairyGUI.Utils;
  6. namespace FairyGUI
  7. {
  8. /// <summary>
  9. ///
  10. /// </summary>
  11. public class TextField : DisplayObject, IMeshFactory
  12. {
  13. VertAlignType _verticalAlign;
  14. TextFormat _textFormat;
  15. bool _input;
  16. string _text;
  17. AutoSizeType _autoSize;
  18. bool _wordWrap;
  19. bool _singleLine;
  20. bool _html;
  21. RTLSupport.DirectionType _textDirection;
  22. int _maxWidth;
  23. List<HtmlElement> _elements;
  24. List<LineInfo> _lines;
  25. List<CharPosition> _charPositions;
  26. BaseFont _font;
  27. float _textWidth;
  28. float _textHeight;
  29. bool _textChanged;
  30. float _yOffset;
  31. float _fontSizeScale;
  32. float _renderScale;
  33. int _fontVersion;
  34. string _parsedText;
  35. int _ellipsisCharIndex;
  36. RichTextField _richTextField;
  37. const int GUTTER_X = 2;
  38. const int GUTTER_Y = 2;
  39. const float IMAGE_BASELINE = 0.8f;
  40. const int ELLIPSIS_LENGTH = 2;
  41. static float[] STROKE_OFFSET = new float[]
  42. {
  43. -1, 0, 1, 0,
  44. 0, -1, 0, 1,
  45. -1, -1, 1, -1,
  46. -1, 1, 1, 1
  47. };
  48. static List<LineCharInfo> sLineChars = new List<LineCharInfo>();
  49. public TextField()
  50. {
  51. _flags |= Flags.TouchDisabled;
  52. _textFormat = new TextFormat();
  53. _fontSizeScale = 1;
  54. _renderScale = UIContentScaler.scaleFactor;
  55. _wordWrap = false;
  56. _text = string.Empty;
  57. _parsedText = string.Empty;
  58. _elements = new List<HtmlElement>(0);
  59. _lines = new List<LineInfo>(1);
  60. CreateGameObject("TextField");
  61. graphics = new NGraphics(gameObject);
  62. graphics.meshFactory = this;
  63. }
  64. internal void EnableRichSupport(RichTextField richTextField)
  65. {
  66. _richTextField = richTextField;
  67. if (richTextField is InputTextField)
  68. {
  69. _input = true;
  70. EnableCharPositionSupport();
  71. }
  72. }
  73. public void EnableCharPositionSupport()
  74. {
  75. if (_charPositions == null)
  76. {
  77. _charPositions = new List<CharPosition>();
  78. _textChanged = true;
  79. }
  80. }
  81. /// <summary>
  82. ///
  83. /// </summary>
  84. public TextFormat textFormat
  85. {
  86. get { return _textFormat; }
  87. set
  88. {
  89. _textFormat = value;
  90. ApplyFormat();
  91. }
  92. }
  93. /// <summary>
  94. ///
  95. /// </summary>
  96. public void ApplyFormat()
  97. {
  98. string fontName = _textFormat.font;
  99. if (string.IsNullOrEmpty(fontName))
  100. fontName = UIConfig.defaultFont;
  101. BaseFont newFont = FontManager.GetFont(fontName);
  102. if (_font != newFont)
  103. {
  104. _font = newFont;
  105. _fontVersion = _font.version;
  106. graphics.SetShaderAndTexture(_font.shader, _font.mainTexture);
  107. }
  108. if (!string.IsNullOrEmpty(_text))
  109. _textChanged = true;
  110. }
  111. /// <summary>
  112. ///
  113. /// </summary>
  114. public AlignType align
  115. {
  116. get { return _textFormat.align; }
  117. set
  118. {
  119. if (_textFormat.align != value)
  120. {
  121. _textFormat.align = value;
  122. if (!string.IsNullOrEmpty(_text))
  123. _textChanged = true;
  124. }
  125. }
  126. }
  127. /// <summary>
  128. ///
  129. /// </summary>
  130. public VertAlignType verticalAlign
  131. {
  132. get
  133. {
  134. return _verticalAlign;
  135. }
  136. set
  137. {
  138. if (_verticalAlign != value)
  139. {
  140. _verticalAlign = value;
  141. if (!_textChanged)
  142. ApplyVertAlign();
  143. }
  144. }
  145. }
  146. /// <summary>
  147. ///
  148. /// </summary>
  149. public string text
  150. {
  151. get { return _text; }
  152. set
  153. {
  154. if (_text == value && !_html)
  155. return;
  156. _text = value;
  157. _textChanged = true;
  158. _html = false;
  159. }
  160. }
  161. /// <summary>
  162. ///
  163. /// </summary>
  164. public string htmlText
  165. {
  166. get { return _text; }
  167. set
  168. {
  169. if (_text == value && _html)
  170. return;
  171. _text = value;
  172. _textChanged = true;
  173. _html = true;
  174. }
  175. }
  176. public string parsedText
  177. {
  178. get { return _parsedText; }
  179. }
  180. /// <summary>
  181. ///
  182. /// </summary>
  183. public AutoSizeType autoSize
  184. {
  185. get { return _autoSize; }
  186. set
  187. {
  188. if (_autoSize != value)
  189. {
  190. _autoSize = value;
  191. _textChanged = true;
  192. }
  193. }
  194. }
  195. /// <summary>
  196. ///
  197. /// </summary>
  198. public bool wordWrap
  199. {
  200. get { return _wordWrap; }
  201. set
  202. {
  203. if (_wordWrap != value)
  204. {
  205. _wordWrap = value;
  206. _textChanged = true;
  207. }
  208. }
  209. }
  210. /// <summary>
  211. ///
  212. /// </summary>
  213. public bool singleLine
  214. {
  215. get { return _singleLine; }
  216. set
  217. {
  218. if (_singleLine != value)
  219. {
  220. _singleLine = value;
  221. _textChanged = true;
  222. }
  223. }
  224. }
  225. /// <summary>
  226. ///
  227. /// </summary>
  228. public float stroke
  229. {
  230. get
  231. {
  232. return _textFormat.outline;
  233. }
  234. set
  235. {
  236. if (_textFormat.outline != value)
  237. {
  238. _textFormat.outline = value;
  239. graphics.SetMeshDirty();
  240. }
  241. }
  242. }
  243. /// <summary>
  244. ///
  245. /// </summary>
  246. public Color strokeColor
  247. {
  248. get
  249. {
  250. return _textFormat.outlineColor;
  251. }
  252. set
  253. {
  254. if (_textFormat.outlineColor != value)
  255. {
  256. _textFormat.outlineColor = value;
  257. graphics.SetMeshDirty();
  258. }
  259. }
  260. }
  261. /// <summary>
  262. ///
  263. /// </summary>
  264. public Vector2 shadowOffset
  265. {
  266. get
  267. {
  268. return _textFormat.shadowOffset;
  269. }
  270. set
  271. {
  272. _textFormat.shadowOffset = value;
  273. graphics.SetMeshDirty();
  274. }
  275. }
  276. /// <summary>
  277. ///
  278. /// </summary>
  279. public float textWidth
  280. {
  281. get
  282. {
  283. if (_textChanged)
  284. BuildLines();
  285. return _textWidth;
  286. }
  287. }
  288. /// <summary>
  289. ///
  290. /// </summary>
  291. public float textHeight
  292. {
  293. get
  294. {
  295. if (_textChanged)
  296. BuildLines();
  297. return _textHeight;
  298. }
  299. }
  300. /// <summary>
  301. ///
  302. /// </summary>
  303. public int maxWidth
  304. {
  305. get { return _maxWidth; }
  306. set
  307. {
  308. if (_maxWidth != value)
  309. {
  310. _maxWidth = value;
  311. _textChanged = true;
  312. }
  313. }
  314. }
  315. /// <summary>
  316. ///
  317. /// </summary>
  318. public List<HtmlElement> htmlElements
  319. {
  320. get
  321. {
  322. if (_textChanged)
  323. BuildLines();
  324. return _elements;
  325. }
  326. }
  327. /// <summary>
  328. ///
  329. /// </summary>
  330. public List<LineInfo> lines
  331. {
  332. get
  333. {
  334. if (_textChanged)
  335. BuildLines();
  336. return _lines;
  337. }
  338. }
  339. /// <summary>
  340. ///
  341. /// </summary>
  342. public List<CharPosition> charPositions
  343. {
  344. get
  345. {
  346. if (_textChanged)
  347. BuildLines();
  348. graphics.UpdateMesh();
  349. return _charPositions;
  350. }
  351. }
  352. /// <summary>
  353. ///
  354. /// </summary>
  355. public RichTextField richTextField
  356. {
  357. get { return _richTextField; }
  358. }
  359. /// <summary>
  360. ///
  361. /// </summary>
  362. public bool Redraw()
  363. {
  364. if (_font == null)
  365. {
  366. _font = FontManager.GetFont(UIConfig.defaultFont);
  367. graphics.SetShaderAndTexture(_font.shader, _font.mainTexture);
  368. _fontVersion = _font.version;
  369. _textChanged = true;
  370. }
  371. if (_font.keepCrisp && _renderScale != UIContentScaler.scaleFactor)
  372. _textChanged = true;
  373. if (_font.version != _fontVersion)
  374. {
  375. _fontVersion = _font.version;
  376. if (_font.mainTexture != graphics.texture)
  377. {
  378. graphics.SetShaderAndTexture(_font.shader, _font.mainTexture);
  379. InvalidateBatchingState();
  380. }
  381. _textChanged = true;
  382. }
  383. if (_textChanged)
  384. BuildLines();
  385. return graphics.UpdateMesh();
  386. }
  387. /// <summary>
  388. ///
  389. /// </summary>
  390. public bool HasCharacter(char ch)
  391. {
  392. return _font.HasCharacter(ch);
  393. }
  394. /// <summary>
  395. ///
  396. /// </summary>
  397. /// <param name="startLine"></param>
  398. /// <param name="startCharX"></param>
  399. /// <param name="endLine"></param>
  400. /// <param name="endCharX"></param>
  401. /// <param name="clipped"></param>
  402. /// <param name="resultRects"></param>
  403. public void GetLinesShape(int startLine, float startCharX, int endLine, float endCharX,
  404. bool clipped,
  405. List<Rect> resultRects)
  406. {
  407. LineInfo line1 = _lines[startLine];
  408. LineInfo line2 = _lines[endLine];
  409. bool leftAlign = _textFormat.align == AlignType.Left;
  410. if (startLine == endLine)
  411. {
  412. Rect r = Rect.MinMaxRect(startCharX, line1.y, endCharX, line1.y + line1.height);
  413. if (clipped)
  414. resultRects.Add(ToolSet.Intersection(ref r, ref _contentRect));
  415. else
  416. resultRects.Add(r);
  417. }
  418. else if (startLine == endLine - 1)
  419. {
  420. Rect r = Rect.MinMaxRect(startCharX, line1.y, leftAlign ? (GUTTER_X + line1.width) : _contentRect.xMax, line1.y + line1.height);
  421. if (clipped)
  422. resultRects.Add(ToolSet.Intersection(ref r, ref _contentRect));
  423. else
  424. resultRects.Add(r);
  425. r = Rect.MinMaxRect(GUTTER_X, line1.y + line1.height, endCharX, line2.y + line2.height);
  426. if (clipped)
  427. resultRects.Add(ToolSet.Intersection(ref r, ref _contentRect));
  428. else
  429. resultRects.Add(r);
  430. }
  431. else
  432. {
  433. Rect r = Rect.MinMaxRect(startCharX, line1.y, leftAlign ? (GUTTER_X + line1.width) : _contentRect.xMax, line1.y + line1.height);
  434. if (clipped)
  435. resultRects.Add(ToolSet.Intersection(ref r, ref _contentRect));
  436. else
  437. resultRects.Add(r);
  438. for (int i = startLine + 1; i < endLine; i++)
  439. {
  440. LineInfo line = _lines[i];
  441. r = Rect.MinMaxRect(GUTTER_X, r.yMax, leftAlign ? (GUTTER_X + line.width) : _contentRect.xMax, line.y + line.height);
  442. if (clipped)
  443. resultRects.Add(ToolSet.Intersection(ref r, ref _contentRect));
  444. else
  445. resultRects.Add(r);
  446. }
  447. r = Rect.MinMaxRect(GUTTER_X, r.yMax, endCharX, line2.y + line2.height);
  448. if (clipped)
  449. resultRects.Add(ToolSet.Intersection(ref r, ref _contentRect));
  450. else
  451. resultRects.Add(r);
  452. }
  453. }
  454. override protected void OnSizeChanged()
  455. {
  456. if ((_flags & Flags.UpdatingSize) == 0)
  457. {
  458. if (_autoSize == AutoSizeType.Shrink || _autoSize == AutoSizeType.Ellipsis || _wordWrap && (_flags & Flags.WidthChanged) != 0)
  459. _textChanged = true;
  460. else if (_autoSize != AutoSizeType.None)
  461. graphics.SetMeshDirty();
  462. if (_verticalAlign != VertAlignType.Top)
  463. ApplyVertAlign();
  464. }
  465. base.OnSizeChanged();
  466. }
  467. public override void EnsureSizeCorrect()
  468. {
  469. if (_textChanged && _autoSize != AutoSizeType.None)
  470. BuildLines();
  471. }
  472. public override void Update(UpdateContext context)
  473. {
  474. if (_richTextField == null) //如果是richTextField,会在update前主动调用了Redraw
  475. Redraw();
  476. base.Update(context);
  477. }
  478. /// <summary>
  479. /// 准备字体纹理
  480. /// </summary>
  481. void RequestText()
  482. {
  483. if (!_html)
  484. {
  485. _font.SetFormat(_textFormat, _fontSizeScale);
  486. _font.PrepareCharacters(_parsedText);
  487. if (_autoSize == AutoSizeType.Ellipsis)
  488. _font.PrepareCharacters("…");
  489. }
  490. else
  491. {
  492. int count = _elements.Count;
  493. for (int i = 0; i < count; i++)
  494. {
  495. HtmlElement element = _elements[i];
  496. if (element.type == HtmlElementType.Text)
  497. {
  498. _font.SetFormat(element.format, _fontSizeScale);
  499. _font.PrepareCharacters(element.text);
  500. if (_autoSize == AutoSizeType.Ellipsis)
  501. _font.PrepareCharacters("…");
  502. }
  503. }
  504. }
  505. }
  506. void BuildLines()
  507. {
  508. if (_font == null)
  509. {
  510. _font = FontManager.GetFont(UIConfig.defaultFont);
  511. _fontVersion = _font.version;
  512. graphics.SetShaderAndTexture(_font.shader, _font.mainTexture);
  513. }
  514. _textChanged = false;
  515. graphics.SetMeshDirty();
  516. _renderScale = UIContentScaler.scaleFactor;
  517. _fontSizeScale = 1;
  518. _ellipsisCharIndex = -1;
  519. Cleanup();
  520. if (_text.Length == 0)
  521. {
  522. LineInfo emptyLine = LineInfo.Borrow();
  523. emptyLine.width = 0;
  524. emptyLine.height = _font.GetLineHeight(_textFormat.size);
  525. emptyLine.charIndex = emptyLine.charCount = 0;
  526. emptyLine.y = emptyLine.y2 = GUTTER_Y;
  527. _lines.Add(emptyLine);
  528. _textWidth = _textHeight = 0;
  529. }
  530. else
  531. {
  532. ParseText();
  533. BuildLines2();
  534. if (_autoSize == AutoSizeType.Shrink)
  535. DoShrink();
  536. }
  537. if (_autoSize == AutoSizeType.Both)
  538. {
  539. _flags |= Flags.UpdatingSize;
  540. if (_richTextField != null)
  541. {
  542. if (_input)
  543. {
  544. float w = Mathf.Max(_textFormat.size, _textWidth);
  545. float h = Mathf.Max(_font.GetLineHeight(_textFormat.size) + GUTTER_Y * 2, _textHeight);
  546. _richTextField.SetSize(w, h);
  547. }
  548. else
  549. _richTextField.SetSize(_textWidth, _textHeight);
  550. }
  551. else
  552. SetSize(_textWidth, _textHeight);
  553. InvalidateBatchingState();
  554. _flags &= ~Flags.UpdatingSize;
  555. }
  556. else if (_autoSize == AutoSizeType.Height)
  557. {
  558. _flags |= Flags.UpdatingSize;
  559. if (_richTextField != null)
  560. {
  561. if (_input)
  562. _richTextField.height = Mathf.Max(_font.GetLineHeight(_textFormat.size) + GUTTER_Y * 2, _textHeight);
  563. else
  564. _richTextField.height = _textHeight;
  565. }
  566. else
  567. this.height = _textHeight;
  568. InvalidateBatchingState();
  569. _flags &= ~Flags.UpdatingSize;
  570. }
  571. _yOffset = 0;
  572. ApplyVertAlign();
  573. }
  574. void ParseText()
  575. {
  576. #if RTL_TEXT_SUPPORT
  577. _textDirection = RTLSupport.DetectTextDirection(_text);
  578. #endif
  579. if (_html)
  580. {
  581. HtmlParser.inst.Parse(_text, _textFormat, _elements,
  582. _richTextField != null ? _richTextField.htmlParseOptions : null);
  583. _parsedText = string.Empty;
  584. }
  585. else
  586. _parsedText = _text;
  587. int elementCount = _elements.Count;
  588. if (elementCount == 0)
  589. {
  590. if (_textDirection != RTLSupport.DirectionType.UNKNOW)
  591. _parsedText = RTLSupport.DoMapping(_parsedText);
  592. bool flag = _input || _richTextField != null && _richTextField.emojies != null;
  593. if (!flag)
  594. {
  595. //检查文本中是否有需要转换的字符,如果没有,节省一个new StringBuilder的操作。
  596. int cnt = _parsedText.Length;
  597. for (int i = 0; i < cnt; i++)
  598. {
  599. char ch = _parsedText[i];
  600. if (ch == '\r' || char.IsHighSurrogate(ch))
  601. {
  602. flag = true;
  603. break;
  604. }
  605. }
  606. }
  607. if (flag)
  608. {
  609. StringBuilder buffer = new StringBuilder();
  610. ParseText(buffer, _parsedText, -1);
  611. elementCount = _elements.Count;
  612. _parsedText = buffer.ToString();
  613. }
  614. }
  615. else
  616. {
  617. StringBuilder buffer = new StringBuilder();
  618. int i = 0;
  619. while (i < elementCount)
  620. {
  621. HtmlElement element = _elements[i];
  622. element.charIndex = buffer.Length;
  623. if (element.type == HtmlElementType.Text)
  624. {
  625. if (_textDirection != RTLSupport.DirectionType.UNKNOW)
  626. element.text = RTLSupport.DoMapping(element.text);
  627. i = ParseText(buffer, element.text, i);
  628. elementCount = _elements.Count;
  629. }
  630. else if (element.isEntity)
  631. buffer.Append(' ');
  632. i++;
  633. }
  634. _parsedText = buffer.ToString();
  635. #if RTL_TEXT_SUPPORT
  636. // element.text拼接完后再进行一次判断文本主语序,避免html标签存在把文本变成混合文本 [2018/12/12/ 16:47:42 by aq_1000]
  637. _textDirection = RTLSupport.DetectTextDirection(_parsedText);
  638. #endif
  639. }
  640. }
  641. void BuildLines2()
  642. {
  643. float letterSpacing = _textFormat.letterSpacing * _fontSizeScale;
  644. float lineSpacing = (_textFormat.lineSpacing - 1) * _fontSizeScale;
  645. float rectWidth = _contentRect.width - GUTTER_X * 2;
  646. float rectHeight = _contentRect.height > 0 ? Mathf.Max(_contentRect.height, _font.GetLineHeight(_textFormat.size)) : 0;
  647. float glyphWidth = 0, glyphHeight = 0, baseline = 0;
  648. short wordLen = 0;
  649. bool wordPossible = false;
  650. float posx = 0;
  651. bool checkEdge = _autoSize == AutoSizeType.Ellipsis;
  652. TextFormat format = _textFormat;
  653. _font.SetFormat(format, _fontSizeScale);
  654. bool wrap = _wordWrap && !_singleLine;
  655. if (_maxWidth > 0)
  656. {
  657. wrap = true;
  658. rectWidth = _maxWidth - GUTTER_X * 2;
  659. }
  660. _textWidth = _textHeight = 0;
  661. RequestText();
  662. int elementCount = _elements.Count;
  663. int elementIndex = 0;
  664. HtmlElement element = null;
  665. if (elementCount > 0)
  666. element = _elements[elementIndex];
  667. int textLength = _parsedText.Length;
  668. LineInfo line = LineInfo.Borrow();
  669. _lines.Add(line);
  670. line.y = line.y2 = GUTTER_Y;
  671. sLineChars.Clear();
  672. for (int charIndex = 0; charIndex < textLength; charIndex++)
  673. {
  674. char ch = _parsedText[charIndex];
  675. glyphWidth = glyphHeight = baseline = 0;
  676. while (element != null && element.charIndex == charIndex)
  677. {
  678. if (element.type == HtmlElementType.Text)
  679. {
  680. format = element.format;
  681. _font.SetFormat(format, _fontSizeScale);
  682. }
  683. else
  684. {
  685. IHtmlObject htmlObject = element.htmlObject;
  686. if (_richTextField != null && htmlObject == null)
  687. {
  688. element.space = (int)(rectWidth - line.width - 4);
  689. htmlObject = _richTextField.htmlPageContext.CreateObject(_richTextField, element);
  690. element.htmlObject = htmlObject;
  691. }
  692. if (htmlObject != null)
  693. {
  694. glyphWidth = htmlObject.width + 2;
  695. glyphHeight = htmlObject.height;
  696. baseline = glyphHeight * IMAGE_BASELINE;
  697. }
  698. if (element.isEntity)
  699. ch = '\0'; //indicate it is a place holder
  700. }
  701. elementIndex++;
  702. if (elementIndex < elementCount)
  703. element = _elements[elementIndex];
  704. else
  705. element = null;
  706. }
  707. if (ch == '\0' || ch == '\n')
  708. {
  709. wordPossible = false;
  710. }
  711. else if (_font.GetGlyph(ch == '\t' ? ' ' : ch, out glyphWidth, out glyphHeight, out baseline))
  712. {
  713. if (ch == '\t')
  714. glyphWidth *= 4;
  715. if (wordPossible)
  716. {
  717. if (char.IsWhiteSpace(ch))
  718. {
  719. wordLen = 0;
  720. }
  721. else if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z'
  722. || ch >= '0' && ch <= '9'
  723. || ch == '.' || ch == '"' || ch == '\''
  724. || format.specialStyle == TextFormat.SpecialStyle.Subscript
  725. || format.specialStyle == TextFormat.SpecialStyle.Superscript
  726. || _textDirection != RTLSupport.DirectionType.UNKNOW && RTLSupport.IsArabicLetter(ch))
  727. {
  728. wordLen++;
  729. }
  730. else
  731. wordPossible = false;
  732. }
  733. else if (char.IsWhiteSpace(ch))
  734. {
  735. wordLen = 0;
  736. wordPossible = true;
  737. }
  738. else if (format.specialStyle == TextFormat.SpecialStyle.Subscript
  739. || format.specialStyle == TextFormat.SpecialStyle.Superscript)
  740. {
  741. if (sLineChars.Count > 0)
  742. {
  743. wordLen = 2; //避免上标和下标折到下一行
  744. wordPossible = true;
  745. }
  746. }
  747. else
  748. wordPossible = false;
  749. }
  750. else
  751. wordPossible = false;
  752. sLineChars.Add(new LineCharInfo() { width = glyphWidth, height = glyphHeight, baseline = baseline });
  753. if (glyphWidth != 0)
  754. {
  755. if (posx != 0)
  756. posx += letterSpacing;
  757. posx += glyphWidth;
  758. }
  759. if (ch == '\n' && !_singleLine)
  760. {
  761. UpdateLineInfo(line, letterSpacing, sLineChars.Count);
  762. LineInfo newLine = LineInfo.Borrow();
  763. _lines.Add(newLine);
  764. newLine.y = line.y + (line.height + lineSpacing);
  765. if (newLine.y < GUTTER_Y) //lineSpacing maybe negative
  766. newLine.y = GUTTER_Y;
  767. newLine.y2 = newLine.y;
  768. newLine.charIndex = line.charIndex + line.charCount;
  769. if (checkEdge && line.y + line.height < rectHeight)
  770. _ellipsisCharIndex = line.charIndex + Math.Max(0, line.charCount - ELLIPSIS_LENGTH);
  771. sLineChars.Clear();
  772. wordPossible = false;
  773. posx = 0;
  774. line = newLine;
  775. }
  776. else if (posx > rectWidth)
  777. {
  778. if (wrap)
  779. {
  780. int lineCharCount = sLineChars.Count;
  781. int toMoveChars;
  782. if (wordPossible && wordLen < 20 && lineCharCount > 2) //if word had broken, move word to new line
  783. {
  784. toMoveChars = wordLen;
  785. //we caculate the line width WITHOUT the tailing space
  786. UpdateLineInfo(line, letterSpacing, lineCharCount - (toMoveChars + 1));
  787. line.charCount++; //but keep it in this line.
  788. }
  789. else
  790. {
  791. toMoveChars = lineCharCount > 1 ? 1 : 0; //if only one char here, we cant move it to new line
  792. UpdateLineInfo(line, letterSpacing, lineCharCount - toMoveChars);
  793. }
  794. LineInfo newLine = LineInfo.Borrow();
  795. _lines.Add(newLine);
  796. newLine.y = line.y + (line.height + lineSpacing);
  797. if (newLine.y < GUTTER_Y)
  798. newLine.y = GUTTER_Y;
  799. newLine.y2 = newLine.y;
  800. newLine.charIndex = line.charIndex + line.charCount;
  801. posx = 0;
  802. if (toMoveChars != 0)
  803. {
  804. for (int i = line.charCount; i < lineCharCount; i++)
  805. {
  806. LineCharInfo ci = sLineChars[i];
  807. if (posx != 0)
  808. posx += letterSpacing;
  809. posx += ci.width;
  810. }
  811. sLineChars.RemoveRange(0, line.charCount);
  812. }
  813. else
  814. sLineChars.Clear();
  815. if (checkEdge && line.y + line.height < rectHeight)
  816. _ellipsisCharIndex = line.charIndex + Math.Max(0, line.charCount - ELLIPSIS_LENGTH);
  817. wordPossible = false;
  818. line = newLine;
  819. }
  820. else if (checkEdge && _ellipsisCharIndex == -1)
  821. _ellipsisCharIndex = line.charIndex + Math.Max(0, line.charCount - ELLIPSIS_LENGTH);
  822. }
  823. }
  824. UpdateLineInfo(line, letterSpacing, sLineChars.Count);
  825. if (_textWidth > 0)
  826. _textWidth += GUTTER_X * 2;
  827. _textHeight = line.y + line.height + GUTTER_Y;
  828. if (checkEdge && _textWidth <= _contentRect.width && _textHeight <= _contentRect.height + GUTTER_Y)
  829. _ellipsisCharIndex = -1;
  830. _textWidth = Mathf.RoundToInt(_textWidth);
  831. _textHeight = Mathf.RoundToInt(_textHeight);
  832. }
  833. void UpdateLineInfo(LineInfo line, float letterSpacing, int cnt)
  834. {
  835. for (int i = 0; i < cnt; i++)
  836. {
  837. LineCharInfo ci = sLineChars[i];
  838. if (ci.baseline > line.baseline)
  839. {
  840. line.height += (ci.baseline - line.baseline);
  841. line.baseline = ci.baseline;
  842. }
  843. if (ci.height - ci.baseline > line.height - line.baseline)
  844. line.height += (ci.height - ci.baseline - (line.height - line.baseline));
  845. if (ci.width > 0)
  846. {
  847. if (line.width != 0)
  848. line.width += letterSpacing;
  849. line.width += ci.width;
  850. }
  851. }
  852. if (line.height == 0)
  853. {
  854. if (_lines.Count == 1)
  855. line.height = _textFormat.size;
  856. else
  857. line.height = _lines[_lines.Count - 2].height;
  858. }
  859. if (line.width > _textWidth)
  860. _textWidth = line.width;
  861. line.charCount = (short)cnt;
  862. }
  863. void DoShrink()
  864. {
  865. if (_lines.Count > 1 && _textHeight > _contentRect.height)
  866. {
  867. //多行的情况,涉及到自动换行,得用二分法查找最合适的比例,会消耗多一点计算资源
  868. int low = 0;
  869. int high = _textFormat.size;
  870. //先尝试猜测一个比例
  871. _fontSizeScale = Mathf.Sqrt(_contentRect.height / _textHeight);
  872. int cur = Mathf.FloorToInt(_fontSizeScale * _textFormat.size);
  873. while (true)
  874. {
  875. LineInfo.Return(_lines);
  876. BuildLines2();
  877. if (_textWidth > _contentRect.width || _textHeight > _contentRect.height)
  878. high = cur;
  879. else
  880. low = cur;
  881. if (high - low > 1 || high != low && cur == high)
  882. {
  883. cur = low + (high - low) / 2;
  884. _fontSizeScale = (float)cur / _textFormat.size;
  885. }
  886. else
  887. break;
  888. }
  889. }
  890. else if (_textWidth > _contentRect.width)
  891. {
  892. _fontSizeScale = _contentRect.width / _textWidth;
  893. LineInfo.Return(_lines);
  894. BuildLines2();
  895. if (_textWidth > _contentRect.width) //如果还超出,缩小一点再来一次
  896. {
  897. int size = Mathf.FloorToInt(_textFormat.size * _fontSizeScale);
  898. size--;
  899. _fontSizeScale = (float)size / _textFormat.size;
  900. LineInfo.Return(_lines);
  901. BuildLines2();
  902. }
  903. }
  904. }
  905. int ParseText(StringBuilder buffer, string source, int elementIndex)
  906. {
  907. int textLength = source.Length;
  908. int j = 0;
  909. int appendPos = 0;
  910. bool hasEmojies = _richTextField != null && _richTextField.emojies != null;
  911. while (j < textLength)
  912. {
  913. char ch = source[j];
  914. if (ch == '\r')
  915. {
  916. buffer.Append(source, appendPos, j - appendPos);
  917. if (j != textLength - 1 && source[j + 1] == '\n')
  918. j++;
  919. appendPos = j + 1;
  920. buffer.Append('\n');
  921. }
  922. else
  923. {
  924. bool highSurrogate = char.IsHighSurrogate(ch);
  925. if (hasEmojies)
  926. {
  927. uint emojiKey = 0;
  928. Emoji emoji;
  929. if (highSurrogate)
  930. emojiKey = ((uint)source[j + 1] & 0x03FF) + ((((uint)ch & 0x03FF) + 0x40) << 10);
  931. else
  932. emojiKey = ch;
  933. if (_richTextField.emojies.TryGetValue(emojiKey, out emoji))
  934. {
  935. HtmlElement imageElement = HtmlElement.GetElement(HtmlElementType.Image);
  936. imageElement.Set("src", emoji.url);
  937. if (emoji.width != 0)
  938. imageElement.Set("width", emoji.width);
  939. if (emoji.height != 0)
  940. imageElement.Set("height", emoji.height);
  941. if (highSurrogate)
  942. imageElement.text = source.Substring(j, 2);
  943. else
  944. imageElement.text = source.Substring(j, 1);
  945. imageElement.format.align = _textFormat.align;
  946. _elements.Insert(++elementIndex, imageElement);
  947. buffer.Append(source, appendPos, j - appendPos);
  948. appendPos = j;
  949. imageElement.charIndex = buffer.Length;
  950. }
  951. }
  952. if (highSurrogate)
  953. {
  954. buffer.Append(source, appendPos, j - appendPos);
  955. appendPos = j + 2;
  956. j++;//跳过lowSurrogate
  957. buffer.Append(' ');
  958. }
  959. }
  960. j++;
  961. }
  962. if (appendPos < textLength)
  963. buffer.Append(source, appendPos, j - appendPos);
  964. return elementIndex;
  965. }
  966. public void OnPopulateMesh(VertexBuffer vb)
  967. {
  968. if (_textWidth == 0 && _lines.Count == 1)
  969. {
  970. if (_charPositions != null)
  971. {
  972. _charPositions.Clear();
  973. _charPositions.Add(new CharPosition());
  974. }
  975. if (_richTextField != null)
  976. _richTextField.RefreshObjects();
  977. return;
  978. }
  979. float letterSpacing = _textFormat.letterSpacing * _fontSizeScale;
  980. TextFormat format = _textFormat;
  981. _font.SetFormat(format, _fontSizeScale);
  982. _font.UpdateGraphics(graphics);
  983. float rectWidth = _contentRect.width > 0 ? (_contentRect.width - GUTTER_X * 2) : 0;
  984. float rectHeight = _contentRect.height > 0 ? Mathf.Max(_contentRect.height, _font.GetLineHeight(format.size)) : 0;
  985. if (_charPositions != null)
  986. _charPositions.Clear();
  987. List<Vector3> vertList = vb.vertices;
  988. List<Vector2> uvList = vb.uvs;
  989. List<Vector2> uv2List = vb.uvs2;
  990. List<Color32> colList = vb.colors;
  991. HtmlLink currentLink = null;
  992. float linkStartX = 0;
  993. int linkStartLine = 0;
  994. float posx = 0;
  995. float indent_x;
  996. bool clipping = !_input && (_autoSize == AutoSizeType.None || _autoSize == AutoSizeType.Ellipsis);
  997. bool lineClipped;
  998. AlignType lineAlign;
  999. float glyphWidth, glyphHeight, baseline;
  1000. short vertCount;
  1001. float underlineStart;
  1002. float strikethroughStart;
  1003. int minFontSize;
  1004. int maxFontSize;
  1005. string rtlLine = null;
  1006. int elementIndex = 0;
  1007. int elementCount = _elements.Count;
  1008. HtmlElement element = null;
  1009. if (elementCount > 0)
  1010. element = _elements[elementIndex];
  1011. int lineCount = _lines.Count;
  1012. for (int i = 0; i < lineCount; ++i)
  1013. {
  1014. LineInfo line = _lines[i];
  1015. if (line.charCount == 0)
  1016. continue;
  1017. lineClipped = clipping && i != 0 && line.y + line.height > rectHeight;
  1018. lineAlign = format.align;
  1019. if (element != null && element.charIndex == line.charIndex)
  1020. lineAlign = element.format.align;
  1021. else
  1022. lineAlign = format.align;
  1023. if (_textDirection == RTLSupport.DirectionType.RTL)
  1024. {
  1025. if (lineAlign == AlignType.Center)
  1026. indent_x = (int)((rectWidth + line.width) / 2);
  1027. else if (lineAlign == AlignType.Right)
  1028. indent_x = rectWidth;
  1029. else
  1030. indent_x = line.width + GUTTER_X * 2;
  1031. if (indent_x > rectWidth)
  1032. indent_x = rectWidth;
  1033. posx = indent_x - GUTTER_X;
  1034. }
  1035. else
  1036. {
  1037. if (lineAlign == AlignType.Center)
  1038. indent_x = (int)((rectWidth - line.width) / 2);
  1039. else if (lineAlign == AlignType.Right)
  1040. indent_x = rectWidth - line.width;
  1041. else
  1042. indent_x = 0;
  1043. if (indent_x < 0)
  1044. indent_x = 0;
  1045. posx = GUTTER_X + indent_x;
  1046. }
  1047. int lineCharCount = line.charCount;
  1048. underlineStart = posx;
  1049. strikethroughStart = posx;
  1050. minFontSize = maxFontSize = format.size;
  1051. if (_textDirection != RTLSupport.DirectionType.UNKNOW)
  1052. {
  1053. rtlLine = _parsedText.Substring(line.charIndex, lineCharCount);
  1054. if (_textDirection == RTLSupport.DirectionType.RTL)
  1055. rtlLine = RTLSupport.ConvertLineR(rtlLine);
  1056. else
  1057. rtlLine = RTLSupport.ConvertLineL(rtlLine);
  1058. lineCharCount = rtlLine.Length;
  1059. }
  1060. for (int j = 0; j < lineCharCount; j++)
  1061. {
  1062. int charIndex = line.charIndex + j;
  1063. char ch = rtlLine != null ? rtlLine[j] : _parsedText[charIndex];
  1064. bool isEllipsis = charIndex == _ellipsisCharIndex;
  1065. while (element != null && charIndex == element.charIndex)
  1066. {
  1067. if (element.type == HtmlElementType.Text)
  1068. {
  1069. vertCount = 0;
  1070. if (format.underline != element.format.underline)
  1071. {
  1072. if (format.underline)
  1073. {
  1074. if (!lineClipped)
  1075. {
  1076. float lineWidth;
  1077. if (_textDirection == RTLSupport.DirectionType.UNKNOW)
  1078. lineWidth = (clipping ? Mathf.Clamp(posx, GUTTER_X, GUTTER_X + rectWidth) : posx) - underlineStart;
  1079. else
  1080. lineWidth = underlineStart - (clipping ? Mathf.Clamp(posx, GUTTER_X, GUTTER_X + rectWidth) : posx);
  1081. if (lineWidth > 0)
  1082. vertCount += (short)_font.DrawLine(underlineStart < posx ? underlineStart : posx, -(line.y + line.baseline), lineWidth,
  1083. maxFontSize, 0, vertList, uvList, uv2List, colList);
  1084. }
  1085. maxFontSize = 0;
  1086. }
  1087. else
  1088. underlineStart = posx;
  1089. }
  1090. if (format.strikethrough != element.format.strikethrough)
  1091. {
  1092. if (format.strikethrough)
  1093. {
  1094. if (!lineClipped)
  1095. {
  1096. float lineWidth;
  1097. if (_textDirection == RTLSupport.DirectionType.UNKNOW)
  1098. lineWidth = (clipping ? Mathf.Clamp(posx, GUTTER_X, GUTTER_X + rectWidth) : posx) - strikethroughStart;
  1099. else
  1100. lineWidth = strikethroughStart - (clipping ? Mathf.Clamp(posx, GUTTER_X, GUTTER_X + rectWidth) : posx);
  1101. if (lineWidth > 0)
  1102. vertCount += (short)_font.DrawLine(strikethroughStart < posx ? strikethroughStart : posx, -(line.y + line.baseline), lineWidth,
  1103. minFontSize, 1, vertList, uvList, uv2List, colList);
  1104. }
  1105. minFontSize = int.MaxValue;
  1106. }
  1107. else
  1108. strikethroughStart = posx;
  1109. }
  1110. if (vertCount > 0 && _charPositions != null)
  1111. {
  1112. CharPosition cp = _charPositions[_charPositions.Count - 1];
  1113. cp.vertCount += vertCount;
  1114. _charPositions[_charPositions.Count - 1] = cp;
  1115. }
  1116. format = element.format;
  1117. minFontSize = Math.Min(minFontSize, format.size);
  1118. maxFontSize = Math.Max(maxFontSize, format.size);
  1119. _font.SetFormat(format, _fontSizeScale);
  1120. }
  1121. else if (element.type == HtmlElementType.Link)
  1122. {
  1123. currentLink = (HtmlLink)element.htmlObject;
  1124. if (currentLink != null)
  1125. {
  1126. element.position = Vector2.zero;
  1127. currentLink.SetPosition(0, 0);
  1128. linkStartX = posx;
  1129. linkStartLine = i;
  1130. }
  1131. }
  1132. else if (element.type == HtmlElementType.LinkEnd)
  1133. {
  1134. if (currentLink != null)
  1135. {
  1136. currentLink.SetArea(linkStartLine, linkStartX, i, posx);
  1137. currentLink = null;
  1138. }
  1139. }
  1140. else
  1141. {
  1142. IHtmlObject htmlObj = element.htmlObject;
  1143. if (htmlObj != null)
  1144. {
  1145. if (_textDirection == RTLSupport.DirectionType.RTL)
  1146. posx -= htmlObj.width - 2;
  1147. if (_charPositions != null)
  1148. {
  1149. CharPosition cp = new CharPosition();
  1150. cp.lineIndex = (short)i;
  1151. cp.charIndex = _charPositions.Count;
  1152. cp.imgIndex = (short)(elementIndex + 1);
  1153. cp.offsetX = posx;
  1154. cp.width = (short)htmlObj.width;
  1155. _charPositions.Add(cp);
  1156. }
  1157. if (isEllipsis || lineClipped || clipping && (posx < GUTTER_X || posx > GUTTER_X && posx + htmlObj.width > _contentRect.width - GUTTER_X))
  1158. element.status |= 1;
  1159. else
  1160. element.status &= 254;
  1161. element.position = new Vector2(posx + 1, line.y + line.baseline - htmlObj.height * IMAGE_BASELINE);
  1162. htmlObj.SetPosition(element.position.x, element.position.y);
  1163. if (_textDirection == RTLSupport.DirectionType.RTL)
  1164. posx -= letterSpacing;
  1165. else
  1166. posx += htmlObj.width + letterSpacing + 2;
  1167. }
  1168. }
  1169. if (element.isEntity)
  1170. ch = '\0';
  1171. elementIndex++;
  1172. if (elementIndex < elementCount)
  1173. element = _elements[elementIndex];
  1174. else
  1175. element = null;
  1176. }
  1177. if (isEllipsis)
  1178. ch = '…';
  1179. else if (ch == '\0')
  1180. continue;
  1181. if (_font.GetGlyph(ch == '\t' ? ' ' : ch, out glyphWidth, out glyphHeight, out baseline))
  1182. {
  1183. if (ch == '\t')
  1184. glyphWidth *= 4;
  1185. if (!isEllipsis)
  1186. {
  1187. if (_textDirection == RTLSupport.DirectionType.RTL)
  1188. {
  1189. if (lineClipped || clipping && (rectWidth < 7 || posx != (indent_x - GUTTER_X)) && posx < GUTTER_X - 0.5f) //超出区域,剪裁
  1190. {
  1191. posx -= (letterSpacing + glyphWidth);
  1192. continue;
  1193. }
  1194. posx -= glyphWidth;
  1195. }
  1196. else
  1197. {
  1198. if (lineClipped || clipping && (rectWidth < 7 || posx != (GUTTER_X + indent_x)) && posx + glyphWidth > _contentRect.width - GUTTER_X + 0.5f) //超出区域,剪裁
  1199. {
  1200. posx += letterSpacing + glyphWidth;
  1201. continue;
  1202. }
  1203. }
  1204. }
  1205. vertCount = (short)_font.DrawGlyph(posx, -(line.y + line.baseline), vertList, uvList, uv2List, colList);
  1206. if (_charPositions != null)
  1207. {
  1208. CharPosition cp = new CharPosition();
  1209. cp.lineIndex = (short)i;
  1210. cp.charIndex = _charPositions.Count;
  1211. cp.vertCount = vertCount;
  1212. cp.offsetX = posx;
  1213. cp.width = (short)glyphWidth;
  1214. _charPositions.Add(cp);
  1215. }
  1216. if (_textDirection == RTLSupport.DirectionType.RTL)
  1217. posx -= letterSpacing;
  1218. else
  1219. posx += letterSpacing + glyphWidth;
  1220. }
  1221. else //if GetGlyph failed
  1222. {
  1223. if (_charPositions != null)
  1224. {
  1225. CharPosition cp = new CharPosition();
  1226. cp.lineIndex = (short)i;
  1227. cp.charIndex = _charPositions.Count;
  1228. cp.offsetX = posx;
  1229. _charPositions.Add(cp);
  1230. }
  1231. if (_textDirection == RTLSupport.DirectionType.RTL)
  1232. posx -= letterSpacing;
  1233. else
  1234. posx += letterSpacing;
  1235. }
  1236. if (isEllipsis)
  1237. lineClipped = true;
  1238. }//text loop
  1239. if (!lineClipped)
  1240. {
  1241. vertCount = 0;
  1242. if (format.underline)
  1243. {
  1244. float lineWidth;
  1245. if (_textDirection == RTLSupport.DirectionType.UNKNOW)
  1246. lineWidth = (clipping ? Mathf.Clamp(posx, GUTTER_X, GUTTER_X + rectWidth) : posx) - underlineStart;
  1247. else
  1248. lineWidth = underlineStart - (clipping ? Mathf.Clamp(posx, GUTTER_X, GUTTER_X + rectWidth) : posx);
  1249. if (lineWidth > 0)
  1250. vertCount += (short)_font.DrawLine(underlineStart < posx ? underlineStart : posx, -(line.y + line.baseline), lineWidth,
  1251. maxFontSize, 0, vertList, uvList, uv2List, colList);
  1252. }
  1253. if (format.strikethrough)
  1254. {
  1255. float lineWidth;
  1256. if (_textDirection == RTLSupport.DirectionType.UNKNOW)
  1257. lineWidth = (clipping ? Mathf.Clamp(posx, GUTTER_X, GUTTER_X + rectWidth) : posx) - strikethroughStart;
  1258. else
  1259. lineWidth = strikethroughStart - (clipping ? Mathf.Clamp(posx, GUTTER_X, GUTTER_X + rectWidth) : posx);
  1260. if (lineWidth > 0)
  1261. vertCount += (short)_font.DrawLine(strikethroughStart < posx ? strikethroughStart : posx, -(line.y + line.baseline), lineWidth,
  1262. minFontSize, 1, vertList, uvList, uv2List, colList);
  1263. }
  1264. if (vertCount > 0 && _charPositions != null)
  1265. {
  1266. CharPosition cp = _charPositions[_charPositions.Count - 1];
  1267. cp.vertCount += vertCount;
  1268. _charPositions[_charPositions.Count - 1] = cp;
  1269. }
  1270. }
  1271. }//line loop
  1272. if (element != null && element.type == HtmlElementType.LinkEnd && currentLink != null)
  1273. currentLink.SetArea(linkStartLine, linkStartX, lineCount - 1, posx);
  1274. if (_charPositions != null)
  1275. {
  1276. CharPosition cp = new CharPosition();
  1277. cp.lineIndex = (short)(lineCount - 1);
  1278. cp.charIndex = _charPositions.Count;
  1279. cp.offsetX = posx;
  1280. _charPositions.Add(cp);
  1281. }
  1282. int count = vertList.Count;
  1283. if (count > 65000)
  1284. {
  1285. Debug.LogWarning("Text is too large. A mesh may not have more than 65000 vertices.");
  1286. vertList.RemoveRange(65000, count - 65000);
  1287. colList.RemoveRange(65000, count - 65000);
  1288. uvList.RemoveRange(65000, count - 65000);
  1289. if (uv2List.Count > 0)
  1290. uv2List.RemoveRange(65000, count - 65000);
  1291. count = 65000;
  1292. }
  1293. if (_font.customOutline)
  1294. {
  1295. bool hasShadow = _textFormat.shadowOffset.x != 0 || _textFormat.shadowOffset.y != 0;
  1296. int allocCount = count;
  1297. int drawDirs = 0;
  1298. if (_textFormat.outline != 0)
  1299. {
  1300. drawDirs = UIConfig.enhancedTextOutlineEffect ? 8 : 4;
  1301. allocCount += count * drawDirs;
  1302. }
  1303. if (hasShadow)
  1304. allocCount += count;
  1305. if (allocCount > 65000)
  1306. {
  1307. Debug.LogWarning("Text is too large. Outline/shadow effect cannot be completed.");
  1308. allocCount = count;
  1309. }
  1310. if (allocCount != count)
  1311. {
  1312. VertexBuffer vb2 = VertexBuffer.Begin();
  1313. List<Vector3> vertList2 = vb2.vertices;
  1314. List<Color32> colList2 = vb2.colors;
  1315. Color32 col = _textFormat.outlineColor;
  1316. float outline = _textFormat.outline;
  1317. if (outline != 0)
  1318. {
  1319. for (int j = 0; j < drawDirs; j++)
  1320. {
  1321. for (int i = 0; i < count; i++)
  1322. {
  1323. Vector3 vert = vertList[i];
  1324. vertList2.Add(new Vector3(vert.x + STROKE_OFFSET[j * 2] * outline, vert.y + STROKE_OFFSET[j * 2 + 1] * outline, 0));
  1325. colList2.Add(col);
  1326. }
  1327. vb2.uvs.AddRange(uvList);
  1328. if (uv2List.Count > 0)
  1329. vb2.uvs2.AddRange(uv2List);
  1330. }
  1331. }
  1332. if (hasShadow)
  1333. {
  1334. col = _textFormat.shadowColor;
  1335. Vector2 offset = _textFormat.shadowOffset;
  1336. for (int i = 0; i < count; i++)
  1337. {
  1338. Vector3 vert = vertList[i];
  1339. vertList2.Add(new Vector3(vert.x + offset.x, vert.y - offset.y, 0));
  1340. colList2.Add(col);
  1341. }
  1342. vb2.uvs.AddRange(uvList);
  1343. if (uv2List.Count > 0)
  1344. vb2.uvs2.AddRange(uv2List);
  1345. }
  1346. vb.Insert(vb2);
  1347. vb2.End();
  1348. }
  1349. }
  1350. vb.AddTriangles();
  1351. if (_richTextField != null)
  1352. _richTextField.RefreshObjects();
  1353. }
  1354. void Cleanup()
  1355. {
  1356. if (_richTextField != null)
  1357. _richTextField.CleanupObjects();
  1358. HtmlElement.ReturnElements(_elements);
  1359. LineInfo.Return(_lines);
  1360. _textWidth = 0;
  1361. _textHeight = 0;
  1362. _parsedText = string.Empty;
  1363. _textDirection = RTLSupport.DirectionType.UNKNOW;
  1364. if (_charPositions != null)
  1365. _charPositions.Clear();
  1366. }
  1367. void ApplyVertAlign()
  1368. {
  1369. float oldOffset = _yOffset;
  1370. if (_autoSize == AutoSizeType.Both || _autoSize == AutoSizeType.Height
  1371. || _verticalAlign == VertAlignType.Top)
  1372. _yOffset = 0;
  1373. else
  1374. {
  1375. float dh;
  1376. if (_textHeight == 0 && _lines.Count > 0)
  1377. dh = _contentRect.height - _lines[0].height;
  1378. else
  1379. dh = _contentRect.height - _textHeight;
  1380. if (dh < 0)
  1381. dh = 0;
  1382. if (_verticalAlign == VertAlignType.Middle)
  1383. _yOffset = (int)(dh / 2);
  1384. else
  1385. _yOffset = dh;
  1386. }
  1387. if (oldOffset != _yOffset)
  1388. {
  1389. int cnt = _lines.Count;
  1390. for (int i = 0; i < cnt; i++)
  1391. _lines[i].y = _lines[i].y2 + _yOffset;
  1392. graphics.SetMeshDirty();
  1393. }
  1394. }
  1395. /// <summary>
  1396. ///
  1397. /// </summary>
  1398. public class LineInfo
  1399. {
  1400. /// <summary>
  1401. /// 行的宽度
  1402. /// </summary>
  1403. public float width;
  1404. /// <summary>
  1405. /// 行的高度
  1406. /// </summary>
  1407. public float height;
  1408. /// <summary>
  1409. /// 文字渲染基线
  1410. /// </summary>
  1411. public float baseline;
  1412. /// <summary>
  1413. /// 行首的字符索引
  1414. /// </summary>
  1415. public int charIndex;
  1416. /// <summary>
  1417. /// 行包括的字符个数
  1418. /// </summary>
  1419. public short charCount;
  1420. /// <summary>
  1421. /// 行的y轴位置
  1422. /// </summary>
  1423. public float y;
  1424. /// <summary>
  1425. /// 行的y轴位置的备份
  1426. /// </summary>
  1427. internal float y2;
  1428. static Stack<LineInfo> pool = new Stack<LineInfo>();
  1429. /// <summary>
  1430. ///
  1431. /// </summary>
  1432. /// <returns></returns>
  1433. public static LineInfo Borrow()
  1434. {
  1435. if (pool.Count > 0)
  1436. {
  1437. LineInfo ret = pool.Pop();
  1438. ret.width = ret.height = ret.baseline = 0;
  1439. ret.y = ret.y2 = 0;
  1440. ret.charIndex = ret.charCount = 0;
  1441. return ret;
  1442. }
  1443. else
  1444. return new LineInfo();
  1445. }
  1446. /// <summary>
  1447. ///
  1448. /// </summary>
  1449. /// <param name="value"></param>
  1450. public static void Return(LineInfo value)
  1451. {
  1452. pool.Push(value);
  1453. }
  1454. /// <summary>
  1455. ///
  1456. /// </summary>
  1457. /// <param name="values"></param>
  1458. public static void Return(List<LineInfo> values)
  1459. {
  1460. int cnt = values.Count;
  1461. for (int i = 0; i < cnt; i++)
  1462. pool.Push(values[i]);
  1463. values.Clear();
  1464. }
  1465. }
  1466. /// <summary>
  1467. ///
  1468. /// </summary>
  1469. public struct LineCharInfo
  1470. {
  1471. public float width;
  1472. public float height;
  1473. public float baseline;
  1474. }
  1475. /// <summary>
  1476. ///
  1477. /// </summary>
  1478. public struct CharPosition
  1479. {
  1480. /// <summary>
  1481. /// 字符索引
  1482. /// </summary>
  1483. public int charIndex;
  1484. /// <summary>
  1485. /// 字符所在的行索引
  1486. /// </summary>
  1487. public short lineIndex;
  1488. /// <summary>
  1489. /// 字符的x偏移
  1490. /// </summary>
  1491. public float offsetX;
  1492. /// <summary>
  1493. /// 字符占用的顶点数量。
  1494. /// </summary>
  1495. public short vertCount;
  1496. /// <summary>
  1497. /// 字符的宽度
  1498. /// </summary>
  1499. public short width;
  1500. /// <summary>
  1501. /// 大于0表示图片索引。
  1502. /// </summary>
  1503. public short imgIndex;
  1504. }
  1505. }
  1506. }