Hue Preserving Color Blending
TMP_Text.cs
1 #define TMP_PRESENT
2 
3 using UnityEngine;
4 using UnityEngine.UI;
5 using UnityEngine.Events;
6 using UnityEngine.EventSystems;
7 using System;
8 using System.Text;
9 using System.Collections;
10 using System.Collections.Generic;
11 
12 
13 namespace TMPro
14 {
15  public interface ITextElement
16  {
17  Material sharedMaterial { get; }
18 
19  void Rebuild(CanvasUpdate update);
20  int GetInstanceID();
21  }
22 
23  public enum TextAlignmentOptions
24  {
28  TopJustified = _HorizontalAlignmentOptions.Justified | _VerticalAlignmentOptions.Top,
30  TopGeoAligned = _HorizontalAlignmentOptions.Geometry | _VerticalAlignmentOptions.Top,
31 
35  Justified = _HorizontalAlignmentOptions.Justified | _VerticalAlignmentOptions.Middle,
37  CenterGeoAligned = _HorizontalAlignmentOptions.Geometry | _VerticalAlignmentOptions.Middle,
38 
39  BottomLeft = _HorizontalAlignmentOptions.Left | _VerticalAlignmentOptions.Bottom,
41  BottomRight = _HorizontalAlignmentOptions.Right | _VerticalAlignmentOptions.Bottom,
42  BottomJustified = _HorizontalAlignmentOptions.Justified | _VerticalAlignmentOptions.Bottom,
43  BottomFlush = _HorizontalAlignmentOptions.Flush | _VerticalAlignmentOptions.Bottom,
44  BottomGeoAligned = _HorizontalAlignmentOptions.Geometry | _VerticalAlignmentOptions.Bottom,
45 
46  BaselineLeft = _HorizontalAlignmentOptions.Left | _VerticalAlignmentOptions.Baseline,
47  Baseline = _HorizontalAlignmentOptions.Center | _VerticalAlignmentOptions.Baseline,
48  BaselineRight = _HorizontalAlignmentOptions.Right | _VerticalAlignmentOptions.Baseline,
49  BaselineJustified = _HorizontalAlignmentOptions.Justified | _VerticalAlignmentOptions.Baseline,
50  BaselineFlush = _HorizontalAlignmentOptions.Flush | _VerticalAlignmentOptions.Baseline,
51  BaselineGeoAligned = _HorizontalAlignmentOptions.Geometry | _VerticalAlignmentOptions.Baseline,
52 
53  MidlineLeft = _HorizontalAlignmentOptions.Left | _VerticalAlignmentOptions.Geometry,
54  Midline = _HorizontalAlignmentOptions.Center | _VerticalAlignmentOptions.Geometry,
55  MidlineRight = _HorizontalAlignmentOptions.Right | _VerticalAlignmentOptions.Geometry,
56  MidlineJustified = _HorizontalAlignmentOptions.Justified | _VerticalAlignmentOptions.Geometry,
57  MidlineFlush = _HorizontalAlignmentOptions.Flush | _VerticalAlignmentOptions.Geometry,
58  MidlineGeoAligned = _HorizontalAlignmentOptions.Geometry | _VerticalAlignmentOptions.Geometry,
59 
60  CaplineLeft = _HorizontalAlignmentOptions.Left | _VerticalAlignmentOptions.Capline,
61  Capline = _HorizontalAlignmentOptions.Center | _VerticalAlignmentOptions.Capline,
62  CaplineRight = _HorizontalAlignmentOptions.Right | _VerticalAlignmentOptions.Capline,
63  CaplineJustified = _HorizontalAlignmentOptions.Justified | _VerticalAlignmentOptions.Capline,
64  CaplineFlush = _HorizontalAlignmentOptions.Flush | _VerticalAlignmentOptions.Capline,
65  CaplineGeoAligned = _HorizontalAlignmentOptions.Geometry | _VerticalAlignmentOptions.Capline
66  };
67 
72  {
73  Left = 0x1, Center = 0x2, Right = 0x4, Justified = 0x8, Flush = 0x10, Geometry = 0x20
74  }
75 
80  {
81  Top = 0x100, Middle = 0x200, Bottom = 0x400, Baseline = 0x800, Geometry = 0x1000, Capline = 0x2000,
82  }
83 
84 
88  public enum TextRenderFlags
89  {
90  DontRender = 0x0,
91  Render = 0xFF
92  };
93 
94  public enum TMP_TextElementType { Character, Sprite };
95  public enum MaskingTypes { MaskOff = 0, MaskHard = 1, MaskSoft = 2 }; //, MaskTex = 4 };
96  public enum TextOverflowModes { Overflow = 0, Ellipsis = 1, Masking = 2, Truncate = 3, ScrollRect = 4, Page = 5, Linked = 6 };
97  public enum MaskingOffsetMode { Percentage = 0, Pixel = 1 };
98  public enum TextureMappingOptions { Character = 0, Line = 1, Paragraph = 2, MatchAspect = 3 };
99 
100  public enum FontStyles { Normal = 0x0, Bold = 0x1, Italic = 0x2, Underline = 0x4, LowerCase = 0x8, UpperCase = 0x10, SmallCaps = 0x20, Strikethrough = 0x40, Superscript = 0x80, Subscript = 0x100, Highlight = 0x200 };
101  public enum FontWeights { Thin = 100, ExtraLight = 200, Light = 300, Normal = 400, Medium = 500, SemiBold = 600, Bold = 700, Heavy = 800, Black = 900 };
102 
103  public enum TagUnits { Pixels = 0, FontUnits = 1, Percentage = 2 };
104  public enum TagType { None = 0x0, NumericalValue = 0x1, StringValue = 0x2, ColorValue = 0x4 };
105 
106 
110  public abstract class TMP_Text : MaskableGraphic
111  {
115  public string text
116  {
117  get { return m_text; }
118  set { if (m_text == value) return; m_text = old_text = value; m_inputSource = TextInputSources.String; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); }
119  }
120  [SerializeField]
121  [TextArea(3, 10)]
122  protected string m_text;
123 
124 
128  public bool isRightToLeftText
129  {
130  get { return m_isRightToLeft; }
131  set { if (m_isRightToLeft == value) return; m_isRightToLeft = value; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); }
132  }
133  [SerializeField]
134  protected bool m_isRightToLeft = false;
135 
136 
140  public TMP_FontAsset font
141  {
142  get { return m_fontAsset; }
143  set { if (m_fontAsset == value) return; m_fontAsset = value; LoadFontAsset(); m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); }
144  }
145  [SerializeField]
146  protected TMP_FontAsset m_fontAsset;
147  protected TMP_FontAsset m_currentFontAsset;
148  protected bool m_isSDFShader;
149 
150 
154  public virtual Material fontSharedMaterial
155  {
156  get { return m_sharedMaterial; }
157  set { if (m_sharedMaterial == value) return; SetSharedMaterial(value); m_havePropertiesChanged = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetMaterialDirty(); }
158  }
159  [SerializeField]
160  protected Material m_sharedMaterial;
161  protected Material m_currentMaterial;
162  protected MaterialReference[] m_materialReferences = new MaterialReference[32];
163  protected Dictionary<int, int> m_materialReferenceIndexLookup = new Dictionary<int, int>();
164 
165  protected TMP_XmlTagStack<MaterialReference> m_materialReferenceStack = new TMP_XmlTagStack<MaterialReference>(new MaterialReference[16]);
166  protected int m_currentMaterialIndex;
167  //protected int m_sharedMaterialHashCode;
168 
169 
173  public virtual Material[] fontSharedMaterials
174  {
175  get { return GetSharedMaterials(); }
176  set { SetSharedMaterials(value); m_havePropertiesChanged = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetMaterialDirty(); }
177  }
178  [SerializeField]
179  protected Material[] m_fontSharedMaterials;
180 
181 
185  public Material fontMaterial
186  {
187  // Return an Instance of the current material.
188  get { return GetMaterial(m_sharedMaterial); }
189 
190  // Assign new font material
191  set
192  {
193  if (m_sharedMaterial != null && m_sharedMaterial.GetInstanceID() == value.GetInstanceID()) return;
194 
195  m_sharedMaterial = value;
196 
197  m_padding = GetPaddingForMaterial();
198  m_havePropertiesChanged = true;
199  m_isInputParsingRequired = true;
200 
201  SetVerticesDirty();
202  SetMaterialDirty();
203  }
204  }
205  [SerializeField]
206  protected Material m_fontMaterial;
207 
208 
212  public virtual Material[] fontMaterials
213  {
214  get { return GetMaterials(m_fontSharedMaterials); }
215 
216  set { SetSharedMaterials(value); m_havePropertiesChanged = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetMaterialDirty(); }
217  }
218  [SerializeField]
219  protected Material[] m_fontMaterials;
220 
221  protected bool m_isMaterialDirty;
222 
223 
227  public override Color color
228  {
229  get { return m_fontColor; }
230  set { if (m_fontColor == value) return; m_havePropertiesChanged = true; m_fontColor = value; SetVerticesDirty(); }
231  }
232  //[UnityEngine.Serialization.FormerlySerializedAs("m_fontColor")] // Required for backwards compatibility with pre-Unity 4.6 releases.
233  [SerializeField]
234  protected Color32 m_fontColor32 = Color.white;
235  [SerializeField]
236  protected Color m_fontColor = Color.white;
237  protected static Color32 s_colorWhite = new Color32(255, 255, 255, 255);
238  protected Color32 m_underlineColor = s_colorWhite;
239  protected Color32 m_strikethroughColor = s_colorWhite;
240  protected Color32 m_highlightColor = s_colorWhite;
241 
242 
246  public float alpha
247  {
248  get { return m_fontColor.a; }
249  set { if (m_fontColor.a == value) return; m_fontColor.a = value; m_havePropertiesChanged = true; SetVerticesDirty(); }
250  }
251 
252 
257  public bool enableVertexGradient
258  {
259  get { return m_enableVertexGradient; }
260  set { if (m_enableVertexGradient == value) return; m_havePropertiesChanged = true; m_enableVertexGradient = value; SetVerticesDirty(); }
261  }
262  [SerializeField]
263  protected bool m_enableVertexGradient;
264 
265  [SerializeField]
266  protected ColorMode m_colorMode = ColorMode.FourCornersGradient;
267 
273  {
274  get { return m_fontColorGradient; }
275  set { m_havePropertiesChanged = true; m_fontColorGradient = value; SetVerticesDirty(); }
276  }
277  [SerializeField]
278  protected VertexGradient m_fontColorGradient = new VertexGradient(Color.white);
279 
280 
285  {
286  get { return m_fontColorGradientPreset; }
287  set { m_havePropertiesChanged = true; m_fontColorGradientPreset = value; SetVerticesDirty(); }
288  }
289  [SerializeField]
290  protected TMP_ColorGradient m_fontColorGradientPreset;
291 
292 
297  {
298  get { return m_spriteAsset; }
299  set { m_spriteAsset = value; m_havePropertiesChanged = true; m_isInputParsingRequired = true; m_isCalculateSizeRequired = true; SetVerticesDirty(); SetLayoutDirty(); }
300  }
301  [SerializeField]
302  protected TMP_SpriteAsset m_spriteAsset;
303 
304 
308  public bool tintAllSprites
309  {
310  get { return m_tintAllSprites; }
311  set { if (m_tintAllSprites == value) return; m_tintAllSprites = value; m_havePropertiesChanged = true; SetVerticesDirty(); }
312  }
313  [SerializeField]
314  protected bool m_tintAllSprites;
315  protected bool m_tintSprite;
316  protected Color32 m_spriteColor;
317 
318 
322  public bool overrideColorTags
323  {
324  get { return m_overrideHtmlColors; }
325  set { if (m_overrideHtmlColors == value) return; m_havePropertiesChanged = true; m_overrideHtmlColors = value; SetVerticesDirty(); }
326  }
327  [SerializeField]
328  protected bool m_overrideHtmlColors = false;
329 
330 
334  public Color32 faceColor
335  {
336  get
337  {
338  if (m_sharedMaterial == null) return m_faceColor;
339 
340  m_faceColor = m_sharedMaterial.GetColor(ShaderUtilities.ID_FaceColor);
341  return m_faceColor;
342  }
343 
344  set { if (m_faceColor.Compare(value)) return; SetFaceColor(value); m_havePropertiesChanged = true; m_faceColor = value; SetVerticesDirty(); SetMaterialDirty(); }
345  }
346  [SerializeField]
347  protected Color32 m_faceColor = Color.white;
348 
349 
353  public Color32 outlineColor
354  {
355  get
356  {
357  if (m_sharedMaterial == null) return m_outlineColor;
358 
359  m_outlineColor = m_sharedMaterial.GetColor(ShaderUtilities.ID_OutlineColor);
360  return m_outlineColor;
361  }
362 
363  set { if (m_outlineColor.Compare(value)) return; SetOutlineColor(value); m_havePropertiesChanged = true; m_outlineColor = value; SetVerticesDirty(); }
364  }
365  [SerializeField]
366  protected Color32 m_outlineColor = Color.black;
367 
368 
372  public float outlineWidth
373  {
374  get
375  {
376  if (m_sharedMaterial == null) return m_outlineWidth;
377 
378  m_outlineWidth = m_sharedMaterial.GetFloat(ShaderUtilities.ID_OutlineWidth);
379  return m_outlineWidth;
380  }
381  set { if (m_outlineWidth == value) return; SetOutlineThickness(value); m_havePropertiesChanged = true; m_outlineWidth = value; SetVerticesDirty(); }
382  }
383  protected float m_outlineWidth = 0.0f;
384 
385 
389  public float fontSize
390  {
391  get { return m_fontSize; }
392  set { if (m_fontSize == value) return; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; m_fontSize = value; if (!m_enableAutoSizing) m_fontSizeBase = m_fontSize; SetVerticesDirty(); SetLayoutDirty(); }
393  }
394  [SerializeField]
395  protected float m_fontSize = 36; // Font Size
396  protected float m_currentFontSize; // Temporary Font Size affected by tags
397  [SerializeField]
398  protected float m_fontSizeBase = 36;
399  protected TMP_XmlTagStack<float> m_sizeStack = new TMP_XmlTagStack<float>(new float[16]);
400 
401 
405  public float fontScale
406  {
407  get { return m_fontScale; }
408  }
409 
410 
414  public int fontWeight
415  {
416  get { return m_fontWeight; }
417  set { if (m_fontWeight == value) return; m_fontWeight = value; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); }
418  }
419  [SerializeField]
420  protected int m_fontWeight = 400;
421  protected int m_fontWeightInternal;
422  protected TMP_XmlTagStack<int> m_fontWeightStack = new TMP_XmlTagStack<int>(new int[16]);
423 
427  public float pixelsPerUnit
428  {
429  get
430  {
431  var localCanvas = canvas;
432  if (!localCanvas)
433  return 1;
434  // For dynamic fonts, ensure we use one pixel per pixel on the screen.
435  if (!font)
436  return localCanvas.scaleFactor;
437  // For non-dynamic fonts, calculate pixels per unit based on specified font size relative to font object's own font size.
438  if (m_currentFontAsset == null || m_currentFontAsset.fontInfo.PointSize <= 0 || m_fontSize <= 0)
439  return 1;
440  return m_fontSize / m_currentFontAsset.fontInfo.PointSize;
441  }
442  }
443 
444 
448  public bool enableAutoSizing
449  {
450  get { return m_enableAutoSizing; }
451  set { if (m_enableAutoSizing == value) return; m_enableAutoSizing = value; SetVerticesDirty(); SetLayoutDirty(); }
452  }
453  [SerializeField]
454  protected bool m_enableAutoSizing;
455  protected float m_maxFontSize; // Used in conjunction with auto-sizing
456  protected float m_minFontSize; // Used in conjunction with auto-sizing
457 
458 
462  public float fontSizeMin
463  {
464  get { return m_fontSizeMin; }
465  set { if (m_fontSizeMin == value) return; m_fontSizeMin = value; SetVerticesDirty(); SetLayoutDirty(); }
466  }
467  [SerializeField]
468  protected float m_fontSizeMin = 0; // Text Auto Sizing Min Font Size.
469 
470 
474  public float fontSizeMax
475  {
476  get { return m_fontSizeMax; }
477  set { if (m_fontSizeMax == value) return; m_fontSizeMax = value; SetVerticesDirty(); SetLayoutDirty(); }
478  }
479  [SerializeField]
480  protected float m_fontSizeMax = 0; // Text Auto Sizing Max Font Size.
481 
482 
486  public FontStyles fontStyle
487  {
488  get { return m_fontStyle; }
489  set { if (m_fontStyle == value) return; m_fontStyle = value; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); }
490  }
491  [SerializeField]
492  protected FontStyles m_fontStyle = FontStyles.Normal;
493  protected FontStyles m_style = FontStyles.Normal;
494  protected TMP_BasicXmlTagStack m_fontStyleStack;
495 
499  public bool isUsingBold { get { return m_isUsingBold; } }
500  protected bool m_isUsingBold = false; // Used to ensure GetPadding & Ratios take into consideration bold characters.
501 
502 
506  public TextAlignmentOptions alignment
507  {
508  get { return m_textAlignment; }
509  set { if (m_textAlignment == value) return; m_havePropertiesChanged = true; m_textAlignment = value; SetVerticesDirty(); }
510  }
511  [SerializeField]
512  [UnityEngine.Serialization.FormerlySerializedAs("m_lineJustification")]
513  protected TextAlignmentOptions m_textAlignment = TextAlignmentOptions.TopLeft;
514  protected TextAlignmentOptions m_lineJustification;
515  protected TMP_XmlTagStack<TextAlignmentOptions> m_lineJustificationStack = new TMP_XmlTagStack<TextAlignmentOptions>(new TextAlignmentOptions[16]);
516  protected Vector3[] m_textContainerLocalCorners = new Vector3[4];
517  [SerializeField]
518  protected bool m_isAlignmentEnumConverted;
519 
523  //public bool alignByGeometry
524  //{
525  // get { return m_alignByGeometry; }
526  // set { if (m_alignByGeometry == value) return; m_havePropertiesChanged = true; m_alignByGeometry = value; SetVerticesDirty(); }
527  //}
528  //[SerializeField]
529  //protected bool m_alignByGeometry;
530 
531 
535  public float characterSpacing
536  {
537  get { return m_characterSpacing; }
538  set { if (m_characterSpacing == value) return; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; m_characterSpacing = value; SetVerticesDirty(); SetLayoutDirty(); }
539  }
540  [SerializeField]
541  protected float m_characterSpacing = 0;
542  protected float m_cSpacing = 0;
543  protected float m_monoSpacing = 0;
544 
548  public float wordSpacing
549  {
550  get { return m_wordSpacing; }
551  set { if (m_wordSpacing == value) return; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; m_wordSpacing = value; SetVerticesDirty(); SetLayoutDirty(); }
552  }
553  [SerializeField]
554  protected float m_wordSpacing = 0;
555 
559  public float lineSpacing
560  {
561  get { return m_lineSpacing; }
562  set { if (m_lineSpacing == value) return; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; m_lineSpacing = value; SetVerticesDirty(); SetLayoutDirty(); }
563  }
564  [SerializeField]
565  protected float m_lineSpacing = 0;
566  protected float m_lineSpacingDelta = 0; // Used with Text Auto Sizing feature
567  protected float m_lineHeight = TMP_Math.FLOAT_UNSET; // Used with the <line-height=xx.x> tag.
568 
569 
573  public float lineSpacingAdjustment
574  {
575  get { return m_lineSpacingMax; }
576  set { if (m_lineSpacingMax == value) return; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; m_lineSpacingMax = value; SetVerticesDirty(); SetLayoutDirty(); }
577  }
578  [SerializeField]
579  protected float m_lineSpacingMax = 0; // Text Auto Sizing Max Line spacing reduction.
580  //protected bool m_forceLineBreak;
581 
585  public float paragraphSpacing
586  {
587  get { return m_paragraphSpacing; }
588  set { if (m_paragraphSpacing == value) return; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; m_paragraphSpacing = value; SetVerticesDirty(); SetLayoutDirty(); }
589  }
590  [SerializeField]
591  protected float m_paragraphSpacing = 0;
592 
593 
597  public float characterWidthAdjustment
598  {
599  get { return m_charWidthMaxAdj; }
600  set { if (m_charWidthMaxAdj == value) return; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; m_charWidthMaxAdj = value; SetVerticesDirty(); SetLayoutDirty(); }
601  }
602  [SerializeField]
603  protected float m_charWidthMaxAdj = 0f; // Text Auto Sizing Max Character Width reduction.
604  protected float m_charWidthAdjDelta = 0;
605 
606 
610  public bool enableWordWrapping
611  {
612  get { return m_enableWordWrapping; }
613  set { if (m_enableWordWrapping == value) return; m_havePropertiesChanged = true; m_isInputParsingRequired = true; m_isCalculateSizeRequired = true; m_enableWordWrapping = value; SetVerticesDirty(); SetLayoutDirty(); }
614  }
615  [SerializeField]
616  protected bool m_enableWordWrapping = false;
617  protected bool m_isCharacterWrappingEnabled = false;
618  protected bool m_isNonBreakingSpace = false;
619  protected bool m_isIgnoringAlignment;
620 
624  public float wordWrappingRatios
625  {
626  get { return m_wordWrappingRatios; }
627  set { if (m_wordWrappingRatios == value) return; m_wordWrappingRatios = value; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; SetVerticesDirty(); SetLayoutDirty(); }
628  }
629  [SerializeField]
630  protected float m_wordWrappingRatios = 0.4f; // Controls word wrapping ratios between word or characters.
631 
632 
636  //public bool enableAdaptiveJustification
637  //{
638  // get { return m_enableAdaptiveJustification; }
639  // set { if (m_enableAdaptiveJustification == value) return; m_enableAdaptiveJustification = value; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; SetVerticesDirty(); SetLayoutDirty(); }
640  //}
641  //[SerializeField]
642  //protected bool m_enableAdaptiveJustification;
643  //protected float m_adaptiveJustificationThreshold = 10.0f;
644 
645 
649  public TextOverflowModes overflowMode
650  {
651  get { return m_overflowMode; }
652  set { if (m_overflowMode == value) return; m_overflowMode = value; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; SetVerticesDirty(); SetLayoutDirty(); }
653  }
654  [SerializeField]
655  protected TextOverflowModes m_overflowMode = TextOverflowModes.Overflow;
656 
657 
661  public bool isTextOverflowing
662  {
663  get { if (m_firstOverflowCharacterIndex != -1) return true; return false; }
664  }
665 
666 
670  public int firstOverflowCharacterIndex
671  {
672  get { return m_firstOverflowCharacterIndex; }
673  }
674  [SerializeField]
675  protected int m_firstOverflowCharacterIndex = -1;
676 
677 
682  {
683  get { return m_linkedTextComponent; }
684 
685  set
686  {
687  if (m_linkedTextComponent != value)
688  {
689  // Release previously linked text component.
690  if (m_linkedTextComponent != null)
691  {
692  m_linkedTextComponent.overflowMode = TextOverflowModes.Overflow;
693  m_linkedTextComponent.linkedTextComponent = null;
694  m_linkedTextComponent.isLinkedTextComponent = false;
695  }
696 
697  m_linkedTextComponent = value;
698 
699  if (m_linkedTextComponent != null)
700  m_linkedTextComponent.isLinkedTextComponent = true;
701  }
702 
703  m_havePropertiesChanged = true;
704  m_isCalculateSizeRequired = true;
705  SetVerticesDirty();
706  SetLayoutDirty();
707  }
708  }
709  [SerializeField]
710  protected TMP_Text m_linkedTextComponent;
711 
712 
716  public bool isLinkedTextComponent
717  {
718  get { return m_isLinkedTextComponent; }
719 
720  set
721  {
722  m_isLinkedTextComponent = value;
723 
724  if (m_isLinkedTextComponent == false)
725  m_firstVisibleCharacter = 0;
726 
727  m_havePropertiesChanged = true;
728  m_isCalculateSizeRequired = true;
729  SetVerticesDirty();
730  SetLayoutDirty();
731  }
732  }
733  [SerializeField]
734  protected bool m_isLinkedTextComponent;
735 
736 
740  public bool isTextTruncated { get { return m_isTextTruncated; } }
741  [SerializeField]
742  protected bool m_isTextTruncated;
743 
744 
748  public bool enableKerning
749  {
750  get { return m_enableKerning; }
751  set { if (m_enableKerning == value) return; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; m_enableKerning = value; SetVerticesDirty(); SetLayoutDirty(); }
752  }
753  [SerializeField]
754  protected bool m_enableKerning;
755 
756 
760  public bool extraPadding
761  {
762  get { return m_enableExtraPadding; }
763  set { if (m_enableExtraPadding == value) return; m_havePropertiesChanged = true; m_enableExtraPadding = value; UpdateMeshPadding(); /* m_isCalculateSizeRequired = true;*/ SetVerticesDirty(); /* SetLayoutDirty();*/ }
764  }
765  [SerializeField]
766  protected bool m_enableExtraPadding = false;
767  [SerializeField]
768  protected bool checkPaddingRequired;
769 
770 
774  public bool richText
775  {
776  get { return m_isRichText; }
777  set { if (m_isRichText == value) return; m_isRichText = value; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); }
778  }
779  [SerializeField]
780  protected bool m_isRichText = true; // Used to enable or disable Rich Text.
781 
782 
786  public bool parseCtrlCharacters
787  {
788  get { return m_parseCtrlCharacters; }
789  set { if (m_parseCtrlCharacters == value) return; m_parseCtrlCharacters = value; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); }
790  }
791  [SerializeField]
792  protected bool m_parseCtrlCharacters = true;
793 
794 
798  public bool isOverlay
799  {
800  get { return m_isOverlay; }
801  set { if (m_isOverlay == value) return; m_isOverlay = value; SetShaderDepth(); m_havePropertiesChanged = true; SetVerticesDirty(); }
802  }
803  protected bool m_isOverlay = false;
804 
805 
809  public bool isOrthographic
810  {
811  get { return m_isOrthographic; }
812  set { if (m_isOrthographic == value) return; m_havePropertiesChanged = true; m_isOrthographic = value; SetVerticesDirty(); }
813  }
814  [SerializeField]
815  protected bool m_isOrthographic = false;
816 
817 
821  public bool enableCulling
822  {
823  get { return m_isCullingEnabled; }
824  set { if (m_isCullingEnabled == value) return; m_isCullingEnabled = value; SetCulling(); m_havePropertiesChanged = true; }
825  }
826  [SerializeField]
827  protected bool m_isCullingEnabled = false;
828 
832  public bool ignoreRectMaskCulling
833  {
834  get { return m_ignoreRectMaskCulling; }
835  set { if (m_ignoreRectMaskCulling == value) return; m_ignoreRectMaskCulling = value; m_havePropertiesChanged = true; }
836  }
837  [SerializeField]
838  protected bool m_ignoreRectMaskCulling;
839 
840 
844  public bool ignoreVisibility
845  {
846  get { return m_ignoreCulling; }
847  set { if (m_ignoreCulling == value) return; m_havePropertiesChanged = true; m_ignoreCulling = value; }
848  }
849  [SerializeField]
850  protected bool m_ignoreCulling = true; // Not implemented yet.
851 
852 
856  public TextureMappingOptions horizontalMapping
857  {
858  get { return m_horizontalMapping; }
859  set { if (m_horizontalMapping == value) return; m_havePropertiesChanged = true; m_horizontalMapping = value; SetVerticesDirty(); }
860  }
861  [SerializeField]
862  protected TextureMappingOptions m_horizontalMapping = TextureMappingOptions.Character;
863 
864 
868  public TextureMappingOptions verticalMapping
869  {
870  get { return m_verticalMapping; }
871  set { if (m_verticalMapping == value) return; m_havePropertiesChanged = true; m_verticalMapping = value; SetVerticesDirty(); }
872  }
873  [SerializeField]
874  protected TextureMappingOptions m_verticalMapping = TextureMappingOptions.Character;
875 
876 
880  //public Vector2 mappingUvOffset
881  //{
882  // get { return m_uvOffset; }
883  // set { if (m_uvOffset == value) return; m_havePropertiesChanged = true; m_uvOffset = value; SetVerticesDirty(); }
884  //}
885  //[SerializeField]
886  //protected Vector2 m_uvOffset = Vector2.zero; // Used to offset UV on Texturing
887 
888 
892  public float mappingUvLineOffset
893  {
894  get { return m_uvLineOffset; }
895  set { if (m_uvLineOffset == value) return; m_havePropertiesChanged = true; m_uvLineOffset = value; SetVerticesDirty(); }
896  }
897  [SerializeField]
898  protected float m_uvLineOffset = 0.0f; // Used for UV line offset per line
899 
900 
905  {
906  get { return m_renderMode; }
907  set { if (m_renderMode == value) return; m_renderMode = value; m_havePropertiesChanged = true; }
908  }
909  protected TextRenderFlags m_renderMode = TextRenderFlags.Render;
910 
911 
915  public VertexSortingOrder geometrySortingOrder
916  {
917  get { return m_geometrySortingOrder; }
918 
919  set { m_geometrySortingOrder = value; m_havePropertiesChanged = true; SetVerticesDirty(); }
920 
921  }
922  [SerializeField]
923  protected VertexSortingOrder m_geometrySortingOrder;
924 
928  public int firstVisibleCharacter
929  {
930  get { return m_firstVisibleCharacter; }
931  set { if (m_firstVisibleCharacter == value) return; m_havePropertiesChanged = true; m_firstVisibleCharacter = value; SetVerticesDirty(); }
932  }
933  [SerializeField]
934  protected int m_firstVisibleCharacter;
935 
939  public int maxVisibleCharacters
940  {
941  get { return m_maxVisibleCharacters; }
942  set { if (m_maxVisibleCharacters == value) return; m_havePropertiesChanged = true; m_maxVisibleCharacters = value; SetVerticesDirty(); }
943  }
944  protected int m_maxVisibleCharacters = 99999;
945 
946 
950  public int maxVisibleWords
951  {
952  get { return m_maxVisibleWords; }
953  set { if (m_maxVisibleWords == value) return; m_havePropertiesChanged = true; m_maxVisibleWords = value; SetVerticesDirty(); }
954  }
955  protected int m_maxVisibleWords = 99999;
956 
957 
961  public int maxVisibleLines
962  {
963  get { return m_maxVisibleLines; }
964  set { if (m_maxVisibleLines == value) return; m_havePropertiesChanged = true; m_isInputParsingRequired = true; m_maxVisibleLines = value; SetVerticesDirty(); }
965  }
966  protected int m_maxVisibleLines = 99999;
967 
968 
972  public bool useMaxVisibleDescender
973  {
974  get { return m_useMaxVisibleDescender; }
975  set { if (m_useMaxVisibleDescender == value) return; m_havePropertiesChanged = true; m_isInputParsingRequired = true; SetVerticesDirty(); }
976  }
977  [SerializeField]
978  protected bool m_useMaxVisibleDescender = true;
979 
980 
984  public int pageToDisplay
985  {
986  get { return m_pageToDisplay; }
987  set { if (m_pageToDisplay == value) return; m_havePropertiesChanged = true; m_pageToDisplay = value; SetVerticesDirty(); }
988  }
989  [SerializeField]
990  protected int m_pageToDisplay = 1;
991  protected bool m_isNewPage = false;
992 
996  public virtual Vector4 margin
997  {
998  get { return m_margin; }
999  set { if (m_margin == value) return; m_margin = value; ComputeMarginSize(); m_havePropertiesChanged = true; SetVerticesDirty(); }
1000  }
1001  [SerializeField]
1002  protected Vector4 m_margin = new Vector4(0, 0, 0, 0);
1003  protected float m_marginLeft;
1004  protected float m_marginRight;
1005  protected float m_marginWidth; // Width of the RectTransform minus left and right margins.
1006  protected float m_marginHeight; // Height of the RectTransform minus top and bottom margins.
1007  protected float m_width = -1;
1008 
1009 
1013  public TMP_TextInfo textInfo
1014  {
1015  get { return m_textInfo; }
1016  }
1017  [SerializeField]
1018  protected TMP_TextInfo m_textInfo; // Class which holds information about the Text object such as characters, lines, mesh data as well as metrics.
1019 
1023  public bool havePropertiesChanged
1024  {
1025  get { return m_havePropertiesChanged; }
1026  set { if (m_havePropertiesChanged == value) return; m_havePropertiesChanged = value; m_isInputParsingRequired = true; SetAllDirty(); }
1027  }
1028  [SerializeField]
1029  protected bool m_havePropertiesChanged; // Used to track when properties of the text object have changed.
1030 
1031 
1036  {
1037  get { return m_isUsingLegacyAnimationComponent; }
1038  set { m_isUsingLegacyAnimationComponent = value; }
1039  }
1040  [SerializeField]
1041  protected bool m_isUsingLegacyAnimationComponent;
1042 
1043 
1047  public new Transform transform
1048  {
1049  get
1050  {
1051  if (m_transform == null)
1052  m_transform = GetComponent<Transform>();
1053  return m_transform;
1054  }
1055  }
1056  protected Transform m_transform;
1057 
1058 
1062  public new RectTransform rectTransform
1063  {
1064  get
1065  {
1066  if (m_rectTransform == null)
1067  m_rectTransform = GetComponent<RectTransform>();
1068  return m_rectTransform;
1069  }
1070  }
1071  protected RectTransform m_rectTransform;
1072 
1073 
1077  public virtual bool autoSizeTextContainer
1078  {
1079  get;
1080  set;
1081  }
1082  protected bool m_autoSizeTextContainer;
1083 
1084 
1088  public virtual Mesh mesh
1089  {
1090  get { return m_mesh; }
1091  }
1092  protected Mesh m_mesh;
1093 
1094 
1098  public bool isVolumetricText
1099  {
1100  get { return m_isVolumetricText; }
1101  set { if (m_isVolumetricText == value) return; m_havePropertiesChanged = value; m_textInfo.ResetVertexLayout(value); m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); }
1102  }
1103  [SerializeField]
1104  protected bool m_isVolumetricText;
1105 
1109  public Bounds bounds
1110  {
1111  get
1112  {
1113  if (m_mesh == null) return new Bounds();
1114 
1115  return GetCompoundBounds();
1116  }
1117  }
1118 
1122  public Bounds textBounds
1123  {
1124  get
1125  {
1126  if (m_textInfo == null) return new Bounds();
1127 
1128  return GetTextBounds();
1129  }
1130  }
1131 
1132  // *** Unity Event Handling ***
1133 
1134  //[Serializable]
1135  //public class TextChangedEvent : UnityEvent { }
1136 
1140  //public TextChangedEvent onTextChanged
1141  //{
1142  // get { return m_OnTextChanged; }
1143  // set { m_OnTextChanged = value; }
1144  //}
1145  //[SerializeField]
1146  //private TextChangedEvent m_OnTextChanged = new TextChangedEvent();
1147 
1148  //protected void SendOnTextChanged()
1149  //{
1150  // if (onTextChanged != null)
1151  // onTextChanged.Invoke();
1152  //}
1153 
1154 
1155  // *** SPECIAL COMPONENTS ***
1156 
1160  //public MarginShaper marginShaper
1161  //{
1162  // get
1163  // {
1164  // if (m_marginShaper == null) m_marginShaper = GetComponent<MarginShaper>();
1165 
1166  // return m_marginShaper;
1167  // }
1168  //}
1169  //[SerializeField]
1170  //protected MarginShaper m_marginShaper;
1171 
1172 
1177  {
1178  get
1179  {
1180  if (m_spriteAnimator == null)
1181  {
1182  m_spriteAnimator = GetComponent<TMP_SpriteAnimator>();
1183  if (m_spriteAnimator == null) m_spriteAnimator = gameObject.AddComponent<TMP_SpriteAnimator>();
1184  }
1185 
1186  return m_spriteAnimator;
1187  }
1188 
1189  }
1190  [SerializeField]
1191  protected TMP_SpriteAnimator m_spriteAnimator;
1192 
1193 
1197  //public TMP_TextShaper textShaper
1198  //{
1199  // get
1200  // {
1201  // if (m_textShaper == null)
1202  // m_textShaper = GetComponent<TMP_TextShaper>();
1203 
1204  // return m_textShaper;
1205  // }
1206  //}
1207  //[SerializeField]
1208  //protected TMP_TextShaper m_textShaper;
1209 
1210  // *** PROPERTIES RELATED TO UNITY LAYOUT SYSTEM ***
1214  public float flexibleHeight { get { return m_flexibleHeight; } }
1215  protected float m_flexibleHeight = -1f;
1216 
1220  public float flexibleWidth { get { return m_flexibleWidth; } }
1221  protected float m_flexibleWidth = -1f;
1222 
1226  public float minWidth { get { return m_minWidth; } }
1227  protected float m_minWidth;
1228 
1232  public float minHeight { get { return m_minHeight; } }
1233  protected float m_minHeight;
1234 
1238  public float maxWidth { get { return m_maxWidth; } }
1239  protected float m_maxWidth;
1240 
1244  public float maxHeight { get { return m_maxHeight; } }
1245  protected float m_maxHeight;
1246 
1250  protected LayoutElement layoutElement
1251  {
1252  get
1253  {
1254  if (m_LayoutElement == null)
1255  {
1256  m_LayoutElement = GetComponent<LayoutElement>();
1257  }
1258 
1259  return m_LayoutElement;
1260  }
1261  }
1262  protected LayoutElement m_LayoutElement;
1263 
1267  public virtual float preferredWidth { get { if (!m_isPreferredWidthDirty) return m_preferredWidth; m_preferredWidth = GetPreferredWidth(); return m_preferredWidth; } }
1268  protected float m_preferredWidth;
1269  protected float m_renderedWidth;
1270  protected bool m_isPreferredWidthDirty;
1271 
1275  public virtual float preferredHeight { get { if (!m_isPreferredHeightDirty) return m_preferredHeight; m_preferredHeight = GetPreferredHeight(); return m_preferredHeight; } }
1276  protected float m_preferredHeight;
1277  protected float m_renderedHeight;
1278  protected bool m_isPreferredHeightDirty;
1279 
1280  protected bool m_isCalculatingPreferredValues;
1281  private int m_recursiveCount;
1282 
1286  public virtual float renderedWidth { get { return GetRenderedWidth(); } }
1287 
1288 
1292  public virtual float renderedHeight { get { return GetRenderedHeight(); } }
1293 
1294 
1298  public int layoutPriority { get { return m_layoutPriority; } }
1299  protected int m_layoutPriority = 0;
1300 
1301  protected bool m_isCalculateSizeRequired = false;
1302  protected bool m_isLayoutDirty;
1303 
1304  protected bool m_verticesAlreadyDirty;
1305  protected bool m_layoutAlreadyDirty;
1306 
1307  protected bool m_isAwake;
1308  protected bool m_isWaitingOnResourceLoad;
1309 
1310  [SerializeField]
1311  protected bool m_isInputParsingRequired = false; // Used to determine if the input text needs to be re-parsed.
1312 
1313  // Protected Fields
1314  protected enum TextInputSources { Text = 0, SetText = 1, SetCharArray = 2, String = 3 };
1315  [SerializeField]
1316  protected TextInputSources m_inputSource;
1317  protected string old_text; // Used by SetText to determine if the text has changed.
1318  //protected float old_arg0, old_arg1, old_arg2; // Used by SetText to determine if the args have changed.
1319 
1320 
1321  protected float m_fontScale; // Scaling of the font based on Atlas true Font Size and Rendered Font Size.
1322  protected float m_fontScaleMultiplier; // Used for handling of superscript and subscript.
1323 
1324  protected char[] m_htmlTag = new char[128]; // Maximum length of rich text tag. This is preallocated to avoid GC.
1325  protected XML_TagAttribute[] m_xmlAttribute = new XML_TagAttribute[8];
1326 
1327  protected float[] m_attributeParameterValues = new float[16];
1328 
1329  protected float tag_LineIndent = 0;
1330  protected float tag_Indent = 0;
1331  protected TMP_XmlTagStack<float> m_indentStack = new TMP_XmlTagStack<float>(new float[16]);
1332  protected bool tag_NoParsing;
1333  //protected TMP_LinkInfo tag_LinkInfo = new TMP_LinkInfo();
1334 
1335  protected bool m_isParsingText;
1336  protected Matrix4x4 m_FXMatrix;
1337  protected bool m_isFXMatrixSet;
1338 
1339 
1340  protected int[] m_char_buffer; // This array holds the characters to be processed by GenerateMesh();
1341  private TMP_CharacterInfo[] m_internalCharacterInfo; // Used by functions to calculate preferred values.
1342  protected char[] m_input_CharArray = new char[256]; // This array hold the characters from the SetText();
1343  private int m_charArray_Length = 0;
1344  protected int m_totalCharacterCount;
1345 
1346  // Structures used to save the state of the text layout in conjunction with line breaking / word wrapping.
1347  protected WordWrapState m_SavedWordWrapState = new WordWrapState();
1348  protected WordWrapState m_SavedLineState = new WordWrapState();
1349  //protected WordWrapState m_SavedAlignment = new WordWrapState ();
1350 
1351 
1352  // Fields whose state is saved in conjunction with text parsing and word wrapping.
1353  protected int m_characterCount;
1354  //protected int m_visibleCharacterCount;
1355  //protected int m_visibleSpriteCount;
1356  protected int m_firstCharacterOfLine;
1357  protected int m_firstVisibleCharacterOfLine;
1358  protected int m_lastCharacterOfLine;
1359  protected int m_lastVisibleCharacterOfLine;
1360  protected int m_lineNumber;
1361  protected int m_lineVisibleCharacterCount;
1362  protected int m_pageNumber;
1363  protected float m_maxAscender;
1364  protected float m_maxCapHeight;
1365  protected float m_maxDescender;
1366  protected float m_maxLineAscender;
1367  protected float m_maxLineDescender;
1368  protected float m_startOfLineAscender;
1369  //protected float m_maxFontScale;
1370  protected float m_lineOffset;
1371  protected Extents m_meshExtents;
1372 
1373 
1374  // Fields used for vertex colors
1375  protected Color32 m_htmlColor = new Color(255, 255, 255, 128);
1376  protected TMP_XmlTagStack<Color32> m_colorStack = new TMP_XmlTagStack<Color32>(new Color32[16]);
1377  protected TMP_XmlTagStack<Color32> m_underlineColorStack = new TMP_XmlTagStack<Color32>(new Color32[16]);
1378  protected TMP_XmlTagStack<Color32> m_strikethroughColorStack = new TMP_XmlTagStack<Color32>(new Color32[16]);
1379  protected TMP_XmlTagStack<Color32> m_highlightColorStack = new TMP_XmlTagStack<Color32>(new Color32[16]);
1380 
1381  protected TMP_ColorGradient m_colorGradientPreset;
1382  protected TMP_XmlTagStack<TMP_ColorGradient> m_colorGradientStack = new TMP_XmlTagStack<TMP_ColorGradient>(new TMP_ColorGradient[16]);
1383 
1384  protected float m_tabSpacing = 0;
1385  protected float m_spacing = 0;
1386 
1387 
1388  //protected bool IsRectTransformDriven;
1389 
1390 
1391  // STYLE TAGS
1392  protected TMP_XmlTagStack<int> m_styleStack = new TMP_XmlTagStack<int>(new int[16]);
1393  protected TMP_XmlTagStack<int> m_actionStack = new TMP_XmlTagStack<int>(new int[16]);
1394 
1395  protected float m_padding = 0;
1396  protected float m_baselineOffset; // Used for superscript and subscript.
1397  protected TMP_XmlTagStack<float> m_baselineOffsetStack = new TMP_XmlTagStack<float>(new float[16]);
1398  protected float m_xAdvance; // Tracks x advancement from character to character.
1399 
1400  protected TMP_TextElementType m_textElementType;
1401  protected TMP_TextElement m_cached_TextElement; // Glyph / Character information is cached into this variable which is faster than having to fetch from the Dictionary multiple times.
1402  protected TMP_Glyph m_cached_Underline_GlyphInfo; // Same as above but for the underline character which is used for Underline.
1403  protected TMP_Glyph m_cached_Ellipsis_GlyphInfo;
1404 
1405  protected TMP_SpriteAsset m_defaultSpriteAsset;
1406  protected TMP_SpriteAsset m_currentSpriteAsset;
1407  protected int m_spriteCount = 0;
1408  protected int m_spriteIndex;
1409  protected int m_spriteAnimationID;
1410  //protected TMP_XmlTagStack<int> m_spriteAnimationStack = new TMP_XmlTagStack<int>(new int[16]);
1411 
1412 
1416  protected virtual void LoadFontAsset() { }
1417 
1422  protected virtual void SetSharedMaterial(Material mat) { }
1423 
1427  protected virtual Material GetMaterial(Material mat) { return null; }
1428 
1433  protected virtual void SetFontBaseMaterial(Material mat) { }
1434 
1439  protected virtual Material[] GetSharedMaterials() { return null; }
1440 
1444  protected virtual void SetSharedMaterials(Material[] materials) { }
1445 
1450  protected virtual Material[] GetMaterials(Material[] mats) { return null; }
1451 
1456  //protected virtual void SetMaterials (Material[] mats) { }
1457 
1463  protected virtual Material CreateMaterialInstance(Material source)
1464  {
1465  Material mat = new Material(source);
1466  mat.shaderKeywords = source.shaderKeywords;
1467  mat.name += " (Instance)";
1468 
1469  return mat;
1470  }
1471 
1472  protected void SetVertexColorGradient(TMP_ColorGradient gradient)
1473  {
1474  if (gradient == null) return;
1475 
1476  m_fontColorGradient.bottomLeft = gradient.bottomLeft;
1477  m_fontColorGradient.bottomRight = gradient.bottomRight;
1478  m_fontColorGradient.topLeft = gradient.topLeft;
1479  m_fontColorGradient.topRight = gradient.topRight;
1480 
1481  SetVerticesDirty();
1482  }
1483 
1487  protected void SetTextSortingOrder(VertexSortingOrder order)
1488  {
1489 
1490  }
1491 
1496  protected void SetTextSortingOrder(int[] order)
1497  {
1498 
1499  }
1500 
1505  protected virtual void SetFaceColor(Color32 color) { }
1506 
1511  protected virtual void SetOutlineColor(Color32 color) { }
1512 
1517  protected virtual void SetOutlineThickness(float thickness) { }
1518 
1522  protected virtual void SetShaderDepth() { }
1523 
1527  protected virtual void SetCulling() { }
1528 
1533  protected virtual float GetPaddingForMaterial() { return 0; }
1534 
1535 
1540  protected virtual float GetPaddingForMaterial(Material mat) { return 0; }
1541 
1542 
1547  protected virtual Vector3[] GetTextContainerLocalCorners() { return null; }
1548 
1549 
1550  // PUBLIC FUNCTIONS
1551  protected bool m_ignoreActiveState;
1555  public virtual void ForceMeshUpdate() { }
1556 
1557 
1562  //protected virtual void ResetVertexLayout() { }
1563 
1564 
1569  public virtual void ForceMeshUpdate(bool ignoreActiveState) { }
1570 
1571 
1575  internal void SetTextInternal(string text)
1576  {
1577  m_text = text;
1578  m_renderMode = TextRenderFlags.DontRender;
1579  m_isInputParsingRequired = true;
1580  ForceMeshUpdate();
1581  m_renderMode = TextRenderFlags.Render;
1582  }
1583 
1588  //public virtual void ForceMeshUpdate(TMP_VertexDataUpdateFlags flags) { }
1589 
1590 
1596  public virtual void UpdateGeometry(Mesh mesh, int index) { }
1597 
1598 
1602  public virtual void UpdateVertexData(TMP_VertexDataUpdateFlags flags) { }
1603 
1604 
1608  public virtual void UpdateVertexData() { }
1609 
1610 
1615  public virtual void SetVertices(Vector3[] vertices) { }
1616 
1617 
1621  public virtual void UpdateMeshPadding() { }
1622 
1623 
1627  //public virtual new void UpdateGeometry() { }
1628 
1629 
1637  public override void CrossFadeColor(Color targetColor, float duration, bool ignoreTimeScale, bool useAlpha)
1638  {
1639  base.CrossFadeColor(targetColor, duration, ignoreTimeScale, useAlpha);
1640  InternalCrossFadeColor(targetColor, duration, ignoreTimeScale, useAlpha);
1641  }
1642 
1643 
1650  public override void CrossFadeAlpha(float alpha, float duration, bool ignoreTimeScale)
1651  {
1652  base.CrossFadeAlpha(alpha, duration, ignoreTimeScale);
1653  InternalCrossFadeAlpha(alpha, duration, ignoreTimeScale);
1654  }
1655 
1656 
1665  protected virtual void InternalCrossFadeColor(Color targetColor, float duration, bool ignoreTimeScale, bool useAlpha) { }
1666 
1667 
1674  protected virtual void InternalCrossFadeAlpha(float alpha, float duration, bool ignoreTimeScale) { }
1675 
1676 
1680  protected void ParseInputText()
1681  {
1682  //Debug.Log("Re-parsing Text.");
1684 
1685  m_isInputParsingRequired = false;
1686 
1687  switch (m_inputSource)
1688  {
1689  case TextInputSources.String:
1690  case TextInputSources.Text:
1691  StringToCharArray(m_text, ref m_char_buffer);
1692  break;
1693  case TextInputSources.SetText:
1694  SetTextArrayToCharArray(m_input_CharArray, ref m_char_buffer);
1695  break;
1696  case TextInputSources.SetCharArray:
1697  break;
1698  }
1699 
1700  SetArraySizes(m_char_buffer);
1702  }
1703 
1704 
1709  public void SetText(string text)
1710  {
1711  SetText(text, true);
1712  }
1713 
1714 
1719  public void SetText(string text, bool syncTextInputBox)
1720  {
1721  //if (text == old_text) return;
1722 
1723  //old_text = text;
1724 
1725  m_inputSource = TextInputSources.SetCharArray;
1726 
1727  StringToCharArray(text, ref m_char_buffer);
1728 
1729  #if UNITY_EDITOR
1730  // Set the text in the Text Input Box in the Unity Editor only.
1731  // TODO: Could revise to convert to string literal
1732  if (syncTextInputBox)
1733  m_text = text;
1734  #endif
1735 
1736  m_isInputParsingRequired = true;
1737  m_havePropertiesChanged = true;
1738  m_isCalculateSizeRequired = true;
1739 
1740  SetVerticesDirty();
1741  SetLayoutDirty();
1742  }
1743 
1744 
1752  public void SetText(string text, float arg0)
1753  {
1754  SetText(text, arg0, 255, 255);
1755  }
1756 
1765  public void SetText(string text, float arg0, float arg1)
1766  {
1767  SetText(text, arg0, arg1, 255);
1768  }
1769 
1779  public void SetText(string text, float arg0, float arg1, float arg2)
1780  {
1781  // Early out if nothing has been changed from previous invocation.
1782  //if (text == old_text && arg0 == old_arg0 && arg1 == old_arg1 && arg2 == old_arg2)
1783  //{
1784  // return;
1785  //}
1786 
1787  //old_text = text;
1788  //old_arg1 = 255;
1789  //old_arg2 = 255;
1790 
1791  int decimalPrecision = 0;
1792  int index = 0;
1793 
1794  for (int i = 0; i < text.Length; i++)
1795  {
1796  char c = text[i];
1797 
1798  if (c == 123) // '{'
1799  {
1800  // Check if user is requesting some decimal precision. Format is {0:2}
1801  if (text[i + 2] == 58) // ':'
1802  {
1803  decimalPrecision = text[i + 3] - 48;
1804  }
1805 
1806  switch (text[i + 1] - 48)
1807  {
1808  case 0: // 1st Arg
1809  //old_arg0 = arg0;
1810  AddFloatToCharArray(arg0, ref index, decimalPrecision);
1811  break;
1812  case 1: // 2nd Arg
1813  //old_arg1 = arg1;
1814  AddFloatToCharArray(arg1, ref index, decimalPrecision);
1815  break;
1816  case 2: // 3rd Arg
1817  //old_arg2 = arg2;
1818  AddFloatToCharArray(arg2, ref index, decimalPrecision);
1819  break;
1820  }
1821 
1822  if (text[i + 2] == 58)
1823  i += 4;
1824  else
1825  i += 2;
1826 
1827  continue;
1828  }
1829  m_input_CharArray[index] = c;
1830  index += 1;
1831  }
1832 
1833  m_input_CharArray[index] = (char)0;
1834  m_charArray_Length = index; // Set the length to where this '0' termination is.
1835 
1836  #if UNITY_EDITOR
1837  // Create new string to be displayed in the Input Text Box of the Editor Panel.
1838  m_text = new string(m_input_CharArray, 0, index);
1839  #endif
1840 
1841  m_inputSource = TextInputSources.SetText;
1842  m_isInputParsingRequired = true;
1843  m_havePropertiesChanged = true;
1844  m_isCalculateSizeRequired = true;
1845 
1846  SetVerticesDirty();
1847  SetLayoutDirty();
1848  }
1849 
1850 
1858  public void SetText(StringBuilder text)
1859  {
1860  m_inputSource = TextInputSources.SetCharArray;
1861 
1862  #if UNITY_EDITOR
1863  // Set the text in the Text Input Box in the Unity Editor only.
1864  m_text = text.ToString();
1865  #endif
1866 
1867  StringBuilderToIntArray(text, ref m_char_buffer);
1868 
1869  m_isInputParsingRequired = true;
1870  m_havePropertiesChanged = true;
1871  m_isCalculateSizeRequired = true;
1872 
1873  SetVerticesDirty();
1874  SetLayoutDirty();
1875  }
1876 
1877 
1882  public void SetCharArray(char[] sourceText)
1883  {
1884  // Initialize internal character buffer if necessary
1885  if (m_char_buffer == null) m_char_buffer = new int[8];
1886 
1887  #if UNITY_EDITOR
1888  // Create new string to be displayed in the Input Text Box of the Editor Panel.
1889  if (sourceText == null || sourceText.Length == 0)
1890  m_text = string.Empty;
1891  else
1892  m_text = new string(sourceText);
1893  #endif
1894 
1895  // Clear the Style stack.
1896  m_styleStack.Clear();
1897 
1898  int writeIndex = 0;
1899 
1900  for (int i = 0; sourceText != null && i < sourceText.Length; i++)
1901  {
1902  if (sourceText[i] == 92 && i < sourceText.Length - 1)
1903  {
1904  switch ((int)sourceText[i + 1])
1905  {
1906  case 110: // \n LineFeed
1907  if (writeIndex == m_char_buffer.Length) ResizeInternalArray(ref m_char_buffer);
1908 
1909  m_char_buffer[writeIndex] = (char)10;
1910  i += 1;
1911  writeIndex += 1;
1912  continue;
1913  case 114: // \r LineFeed
1914  if (writeIndex == m_char_buffer.Length) ResizeInternalArray(ref m_char_buffer);
1915 
1916  m_char_buffer[writeIndex] = (char)13;
1917  i += 1;
1918  writeIndex += 1;
1919  continue;
1920  case 116: // \t Tab
1921  if (writeIndex == m_char_buffer.Length) ResizeInternalArray(ref m_char_buffer);
1922 
1923  m_char_buffer[writeIndex] = (char)9;
1924  i += 1;
1925  writeIndex += 1;
1926  continue;
1927  }
1928  }
1929 
1930  // Handle inline replacement of <stlye> and <br> tags.
1931  if (sourceText[i] == 60)
1932  {
1933  if (IsTagName(ref sourceText, "<BR>", i))
1934  {
1935  if (writeIndex == m_char_buffer.Length) ResizeInternalArray(ref m_char_buffer);
1936 
1937  m_char_buffer[writeIndex] = 10; ;
1938  writeIndex += 1;
1939  i += 3;
1940 
1941  continue;
1942  }
1943  else if (IsTagName(ref sourceText, "<STYLE=", i))
1944  {
1945  int srcOffset = 0;
1946  if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref m_char_buffer, ref writeIndex))
1947  {
1948  i = srcOffset;
1949  continue;
1950  }
1951  }
1952  else if (IsTagName(ref sourceText, "</STYLE>", i))
1953  {
1954  ReplaceClosingStyleTag(ref sourceText, i, ref m_char_buffer, ref writeIndex);
1955 
1956  // Strip </style> even if style is invalid.
1957  i += 7;
1958  continue;
1959  }
1960  }
1961 
1962  if (writeIndex == m_char_buffer.Length) ResizeInternalArray(ref m_char_buffer);
1963 
1964  m_char_buffer[writeIndex] = sourceText[i];
1965  writeIndex += 1;
1966  }
1967 
1968  if (writeIndex == m_char_buffer.Length) ResizeInternalArray(ref m_char_buffer);
1969 
1970  m_char_buffer[writeIndex] = (char)0;
1971 
1972  m_inputSource = TextInputSources.SetCharArray;
1973  m_isInputParsingRequired = true;
1974  m_havePropertiesChanged = true;
1975  m_isCalculateSizeRequired = true;
1976 
1977  SetVerticesDirty();
1978  SetLayoutDirty();
1979  }
1980 
1981 
1986  public void SetCharArray(char[] sourceText, int start, int length)
1987  {
1988  // Initialize internal character buffer if necessary
1989  if (m_char_buffer == null) m_char_buffer = new int[8];
1990 
1991  #if UNITY_EDITOR
1992  // Create new string to be displayed in the Input Text Box of the Editor Panel.
1993  if (sourceText == null || sourceText.Length == 0 || length == 0)
1994  {
1995  m_text = string.Empty;
1996  start = 0;
1997  length = 0;
1998  }
1999  else
2000  {
2001  // TODO: Add potential range check on start + length relative to array size.
2002  m_text = new string(sourceText, start, length);
2003  }
2004  #endif
2005 
2006  // Clear the Style stack.
2007  m_styleStack.Clear();
2008 
2009  int writeIndex = 0;
2010 
2011  int i = start;
2012  int end = start + length;
2013  for (; i < end; i++)
2014  {
2015  if (sourceText[i] == 92 && i < length - 1)
2016  {
2017  switch ((int)sourceText[i + 1])
2018  {
2019  case 110: // \n LineFeed
2020  if (writeIndex == m_char_buffer.Length) ResizeInternalArray(ref m_char_buffer);
2021 
2022  m_char_buffer[writeIndex] = (char)10;
2023  i += 1;
2024  writeIndex += 1;
2025  continue;
2026  case 114: // \r LineFeed
2027  if (writeIndex == m_char_buffer.Length) ResizeInternalArray(ref m_char_buffer);
2028 
2029  m_char_buffer[writeIndex] = (char)13;
2030  i += 1;
2031  writeIndex += 1;
2032  continue;
2033  case 116: // \t Tab
2034  if (writeIndex == m_char_buffer.Length) ResizeInternalArray(ref m_char_buffer);
2035 
2036  m_char_buffer[writeIndex] = (char)9;
2037  i += 1;
2038  writeIndex += 1;
2039  continue;
2040  }
2041  }
2042 
2043  // Handle inline replacement of <stlye> and <br> tags.
2044  if (sourceText[i] == 60)
2045  {
2046  if (IsTagName(ref sourceText, "<BR>", i))
2047  {
2048  if (writeIndex == m_char_buffer.Length) ResizeInternalArray(ref m_char_buffer);
2049 
2050  m_char_buffer[writeIndex] = 10; ;
2051  writeIndex += 1;
2052  i += 3;
2053 
2054  continue;
2055  }
2056  else if (IsTagName(ref sourceText, "<STYLE=", i))
2057  {
2058  int srcOffset = 0;
2059  if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref m_char_buffer, ref writeIndex))
2060  {
2061  i = srcOffset;
2062  continue;
2063  }
2064  }
2065  else if (IsTagName(ref sourceText, "</STYLE>", i))
2066  {
2067  ReplaceClosingStyleTag(ref sourceText, i, ref m_char_buffer, ref writeIndex);
2068 
2069  // Strip </style> even if style is invalid.
2070  i += 7;
2071  continue;
2072  }
2073  }
2074 
2075  if (writeIndex == m_char_buffer.Length) ResizeInternalArray(ref m_char_buffer);
2076 
2077  m_char_buffer[writeIndex] = sourceText[i];
2078  writeIndex += 1;
2079  }
2080 
2081  if (writeIndex == m_char_buffer.Length) ResizeInternalArray(ref m_char_buffer);
2082 
2083  m_char_buffer[writeIndex] = (char)0;
2084 
2085  m_inputSource = TextInputSources.SetCharArray;
2086  m_havePropertiesChanged = true;
2087  m_isInputParsingRequired = true;
2088  m_isCalculateSizeRequired = true;
2089 
2090  SetVerticesDirty();
2091  SetLayoutDirty();
2092  }
2093 
2094 
2099  public void SetCharArray(int[] sourceText, int start, int length)
2100  {
2101  // Initialize internal character buffer if necessary
2102  if (m_char_buffer == null) m_char_buffer = new int[8];
2103 
2104  #if UNITY_EDITOR
2105  // Create new string to be displayed in the Input Text Box of the Editor Panel.
2106  if (sourceText == null || sourceText.Length == 0 || length == 0)
2107  {
2108  m_text = string.Empty;
2109  start = 0;
2110  length = 0;
2111  }
2112  else
2113  {
2114  m_text = sourceText.IntToString(start, length);
2115  }
2116  #endif
2117 
2118  // Clear the Style stack.
2119  m_styleStack.Clear();
2120 
2121  int writeIndex = 0;
2122 
2123  int end = start + length;
2124  for (int i = start; i < end; i++)
2125  {
2126  if (sourceText[i] == 92 && i < length - 1)
2127  {
2128  switch ((int)sourceText[i + 1])
2129  {
2130  case 110: // \n LineFeed
2131  if (writeIndex == m_char_buffer.Length) ResizeInternalArray(ref m_char_buffer);
2132 
2133  m_char_buffer[writeIndex] = (char)10;
2134  i += 1;
2135  writeIndex += 1;
2136  continue;
2137  case 114: // \r LineFeed
2138  if (writeIndex == m_char_buffer.Length) ResizeInternalArray(ref m_char_buffer);
2139 
2140  m_char_buffer[writeIndex] = (char)13;
2141  i += 1;
2142  writeIndex += 1;
2143  continue;
2144  case 116: // \t Tab
2145  if (writeIndex == m_char_buffer.Length) ResizeInternalArray(ref m_char_buffer);
2146 
2147  m_char_buffer[writeIndex] = (char)9;
2148  i += 1;
2149  writeIndex += 1;
2150  continue;
2151  }
2152  }
2153 
2154  // Handle inline replacement of <stlye> and <br> tags.
2155  if (sourceText[i] == 60)
2156  {
2157  if (IsTagName(ref sourceText, "<BR>", i))
2158  {
2159  if (writeIndex == m_char_buffer.Length) ResizeInternalArray(ref m_char_buffer);
2160 
2161  m_char_buffer[writeIndex] = 10; ;
2162  writeIndex += 1;
2163  i += 3;
2164 
2165  continue;
2166  }
2167  else if (IsTagName(ref sourceText, "<STYLE=", i))
2168  {
2169  int srcOffset = 0;
2170  if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref m_char_buffer, ref writeIndex))
2171  {
2172  i = srcOffset;
2173  continue;
2174  }
2175  }
2176  else if (IsTagName(ref sourceText, "</STYLE>", i))
2177  {
2178  ReplaceClosingStyleTag(ref sourceText, i, ref m_char_buffer, ref writeIndex);
2179 
2180  // Strip </style> even if style is invalid.
2181  i += 7;
2182  continue;
2183  }
2184  }
2185 
2186  if (writeIndex == m_char_buffer.Length) ResizeInternalArray(ref m_char_buffer);
2187 
2188  m_char_buffer[writeIndex] = sourceText[i];
2189  writeIndex += 1;
2190  }
2191 
2192  if (writeIndex == m_char_buffer.Length) ResizeInternalArray(ref m_char_buffer);
2193 
2194  m_char_buffer[writeIndex] = (char)0;
2195 
2196  m_inputSource = TextInputSources.SetCharArray;
2197  m_havePropertiesChanged = true;
2198  m_isInputParsingRequired = true;
2199  m_isCalculateSizeRequired = true;
2200 
2201  SetVerticesDirty();
2202  SetLayoutDirty();
2203  }
2204 
2205 
2211  protected void SetTextArrayToCharArray(char[] sourceText, ref int[] charBuffer)
2212  {
2213  //Debug.Log("SetText Array to Char called.");
2214  if (sourceText == null || m_charArray_Length == 0)
2215  return;
2216 
2217  if (charBuffer == null) charBuffer = new int[8];
2218 
2219  // Clear the Style stack.
2220  m_styleStack.Clear();
2221 
2222  int writeIndex = 0;
2223 
2224  for (int i = 0; i < m_charArray_Length; i++)
2225  {
2226  // Handle UTF-32 in the input text (string).
2227  if (char.IsHighSurrogate(sourceText[i]) && char.IsLowSurrogate(sourceText[i + 1]))
2228  {
2229  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2230 
2231  charBuffer[writeIndex] = char.ConvertToUtf32(sourceText[i], sourceText[i + 1]);
2232  i += 1;
2233  writeIndex += 1;
2234  continue;
2235  }
2236 
2237  // Handle inline replacement of <stlye> and <br> tags.
2238  if (sourceText[i] == 60)
2239  {
2240  if (IsTagName(ref sourceText, "<BR>", i))
2241  {
2242  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2243 
2244  charBuffer[writeIndex] = 10;
2245  writeIndex += 1;
2246  i += 3;
2247 
2248  continue;
2249  }
2250  else if (IsTagName(ref sourceText, "<STYLE=", i))
2251  {
2252  int srcOffset = 0;
2253  if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref charBuffer, ref writeIndex))
2254  {
2255  i = srcOffset;
2256  continue;
2257  }
2258  }
2259  else if (IsTagName(ref sourceText, "</STYLE>", i))
2260  {
2261  ReplaceClosingStyleTag(ref sourceText, i, ref charBuffer, ref writeIndex);
2262 
2263  // Strip </style> even if style is invalid.
2264  i += 7;
2265  continue;
2266  }
2267  }
2268 
2269  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2270 
2271  charBuffer[writeIndex] = sourceText[i];
2272  writeIndex += 1;
2273  }
2274 
2275  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2276 
2277  charBuffer[writeIndex] = 0;
2278  }
2279 
2280 
2286  protected void StringToCharArray(string sourceText, ref int[] charBuffer)
2287  {
2288  if (sourceText == null)
2289  {
2290  charBuffer[0] = 0;
2291  return;
2292  }
2293 
2294  if (charBuffer == null) charBuffer = new int[8];
2295 
2296  // Clear the Style stack.
2297  m_styleStack.SetDefault(0);
2298 
2299  int writeIndex = 0;
2300 
2301  for (int i = 0; i < sourceText.Length; i++)
2302  {
2303  if (m_inputSource == TextInputSources.Text && sourceText[i] == 92 && sourceText.Length > i + 1)
2304  {
2305  switch ((int)sourceText[i + 1])
2306  {
2307  case 85: // \U00000000 for UTF-32 Unicode
2308  if (sourceText.Length > i + 9)
2309  {
2310  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2311 
2312  charBuffer[writeIndex] = GetUTF32(sourceText, i + 2);
2313  i += 9;
2314  writeIndex += 1;
2315  continue;
2316  }
2317  break;
2318  case 92: // \ escape
2319  if (!m_parseCtrlCharacters) break;
2320 
2321  if (sourceText.Length <= i + 2) break;
2322 
2323  if (writeIndex + 2 > charBuffer.Length) ResizeInternalArray(ref charBuffer);
2324 
2325  charBuffer[writeIndex] = sourceText[i + 1];
2326  charBuffer[writeIndex + 1] = sourceText[i + 2];
2327  i += 2;
2328  writeIndex += 2;
2329  continue;
2330  case 110: // \n LineFeed
2331  if (!m_parseCtrlCharacters) break;
2332 
2333  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2334 
2335  charBuffer[writeIndex] = (char)10;
2336  i += 1;
2337  writeIndex += 1;
2338  continue;
2339  case 114: // \r
2340  if (!m_parseCtrlCharacters) break;
2341 
2342  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2343 
2344  charBuffer[writeIndex] = (char)13;
2345  i += 1;
2346  writeIndex += 1;
2347  continue;
2348  case 116: // \t Tab
2349  if (!m_parseCtrlCharacters) break;
2350 
2351  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2352 
2353  charBuffer[writeIndex] = (char)9;
2354  i += 1;
2355  writeIndex += 1;
2356  continue;
2357  case 117: // \u0000 for UTF-16 Unicode
2358  if (sourceText.Length > i + 5)
2359  {
2360  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2361 
2362  charBuffer[writeIndex] = (char)GetUTF16(sourceText, i + 2);
2363  i += 5;
2364  writeIndex += 1;
2365  continue;
2366  }
2367  break;
2368  }
2369  }
2370 
2371  // Handle UTF-32 in the input text (string). // Not sure this is needed //
2372  if (char.IsHighSurrogate(sourceText[i]) && char.IsLowSurrogate(sourceText[i + 1]))
2373  {
2374  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2375 
2376  charBuffer[writeIndex] = char.ConvertToUtf32(sourceText[i], sourceText[i + 1]);
2377  i += 1;
2378  writeIndex += 1;
2379  continue;
2380  }
2381 
2383  if (sourceText[i] == 60 && m_isRichText)
2384  {
2385  if (IsTagName(ref sourceText, "<BR>", i))
2386  {
2387  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2388 
2389  charBuffer[writeIndex] = 10; ;
2390  writeIndex += 1;
2391  i += 3;
2392 
2393  continue;
2394  }
2395  else if (IsTagName(ref sourceText, "<STYLE=", i))
2396  {
2397  int srcOffset = 0;
2398  if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref charBuffer, ref writeIndex))
2399  {
2400  i = srcOffset;
2401  continue;
2402  }
2403  }
2404  else if (IsTagName(ref sourceText, "</STYLE>", i))
2405  {
2406  ReplaceClosingStyleTag(ref sourceText, i, ref charBuffer, ref writeIndex);
2407 
2408  // Strip </style> even if style is invalid.
2409  i += 7;
2410  continue;
2411  }
2412  }
2413 
2414  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2415 
2416  charBuffer[writeIndex] = sourceText[i];
2417  writeIndex += 1;
2418  }
2419 
2420  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2421 
2422  charBuffer[writeIndex] = (char)0;
2423  }
2424 
2425 
2431  protected void StringBuilderToIntArray(StringBuilder sourceText, ref int[] charBuffer)
2432  {
2433  if (sourceText == null)
2434  {
2435  charBuffer[0] = 0;
2436  return;
2437  }
2438 
2439  if (charBuffer == null) charBuffer = new int[8];
2440 
2441  // Clear the Style stack.
2442  m_styleStack.Clear();
2443 
2444  #if UNITY_EDITOR
2445  // Create new string to be displayed in the Input Text Box of the Editor Panel.
2446  m_text = sourceText.ToString();
2447  #endif
2448 
2449  int writeIndex = 0;
2450 
2451  for (int i = 0; i < sourceText.Length; i++)
2452  {
2453  if (m_parseCtrlCharacters && sourceText[i] == 92 && sourceText.Length > i + 1)
2454  {
2455  switch ((int)sourceText[i + 1])
2456  {
2457  case 85: // \U00000000 for UTF-32 Unicode
2458  if (sourceText.Length > i + 9)
2459  {
2460  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2461 
2462  charBuffer[writeIndex] = GetUTF32(sourceText, i + 2);
2463  i += 9;
2464  writeIndex += 1;
2465  continue;
2466  }
2467  break;
2468  case 92: // \ escape
2469  if (sourceText.Length <= i + 2) break;
2470 
2471  if (writeIndex + 2 > charBuffer.Length) ResizeInternalArray(ref charBuffer);
2472 
2473  charBuffer[writeIndex] = sourceText[i + 1];
2474  charBuffer[writeIndex + 1] = sourceText[i + 2];
2475  i += 2;
2476  writeIndex += 2;
2477  continue;
2478  case 110: // \n LineFeed
2479  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2480 
2481  charBuffer[writeIndex] = (char)10;
2482  i += 1;
2483  writeIndex += 1;
2484  continue;
2485  case 114: // \r
2486  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2487 
2488  charBuffer[writeIndex] = (char)13;
2489  i += 1;
2490  writeIndex += 1;
2491  continue;
2492  case 116: // \t Tab
2493  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2494 
2495  charBuffer[writeIndex] = (char)9;
2496  i += 1;
2497  writeIndex += 1;
2498  continue;
2499  case 117: // \u0000 for UTF-16 Unicode
2500  if (sourceText.Length > i + 5)
2501  {
2502  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2503 
2504  charBuffer[writeIndex] = (char)GetUTF16(sourceText, i + 2);
2505  i += 5;
2506  writeIndex += 1;
2507  continue;
2508  }
2509  break;
2510  }
2511  }
2512 
2513  // Handle UTF-32 in the input text (string).
2514  if (char.IsHighSurrogate(sourceText[i]) && char.IsLowSurrogate(sourceText[i + 1]))
2515  {
2516  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2517 
2518  charBuffer[writeIndex] = char.ConvertToUtf32(sourceText[i], sourceText[i + 1]);
2519  i += 1;
2520  writeIndex += 1;
2521  continue;
2522  }
2523 
2524  // Handle inline replacement of <stlye> and <br> tags.
2525  if (sourceText[i] == 60)
2526  {
2527  if (IsTagName(ref sourceText, "<BR>", i))
2528  {
2529  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2530 
2531  charBuffer[writeIndex] = 10;
2532  writeIndex += 1;
2533  i += 3;
2534 
2535  continue;
2536  }
2537  else if (IsTagName(ref sourceText, "<STYLE=", i))
2538  {
2539  int srcOffset = 0;
2540  if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref charBuffer, ref writeIndex))
2541  {
2542  i = srcOffset;
2543  continue;
2544  }
2545  }
2546  else if (IsTagName(ref sourceText, "</STYLE>", i))
2547  {
2548  ReplaceClosingStyleTag(ref sourceText, i, ref charBuffer, ref writeIndex);
2549 
2550  // Strip </style> even if style is invalid.
2551  i += 7;
2552  continue;
2553  }
2554  }
2555 
2556  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2557 
2558  charBuffer[writeIndex] = sourceText[i];
2559  writeIndex += 1;
2560  }
2561 
2562  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2563 
2564  charBuffer[writeIndex] = (char)0;
2565  }
2566 
2567 
2577  bool ReplaceOpeningStyleTag(ref string sourceText, int srcIndex, out int srcOffset, ref int[] charBuffer, ref int writeIndex)
2578  {
2579  // Validate <style> tag.
2580  int hashCode = GetTagHashCode(ref sourceText, srcIndex + 7, out srcOffset);
2581 
2582  TMP_Style style = TMP_StyleSheet.GetStyle(hashCode);
2583 
2584  // Return if we don't have a valid style.
2585  if (style == null || srcOffset == 0) return false;
2586 
2587  m_styleStack.Add(style.hashCode);
2588 
2589  int styleLength = style.styleOpeningTagArray.Length;
2590 
2591  // Replace <style> tag with opening definition
2592  int[] openingTagArray = style.styleOpeningTagArray;
2593 
2594  for (int i = 0; i < styleLength; i++)
2595  {
2596  int c = openingTagArray[i];
2597 
2598  if (c == 60)
2599  {
2600  if (IsTagName(ref openingTagArray, "<BR>", i))
2601  {
2602  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2603 
2604  charBuffer[writeIndex] = 10;
2605  writeIndex += 1;
2606  i += 3;
2607 
2608  continue;
2609  }
2610  else if (IsTagName(ref openingTagArray, "<STYLE=", i))
2611  {
2612  int offset = 0;
2613  if (ReplaceOpeningStyleTag(ref openingTagArray, i, out offset, ref charBuffer, ref writeIndex))
2614  {
2615  i = offset;
2616  continue;
2617  }
2618  }
2619  else if (IsTagName(ref openingTagArray, "</STYLE>", i))
2620  {
2621  ReplaceClosingStyleTag(ref openingTagArray, i, ref charBuffer, ref writeIndex);
2622 
2623  // Strip </style> even if style is invalid.
2624  i += 7;
2625  continue;
2626  }
2627  }
2628 
2629  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2630 
2631  charBuffer[writeIndex] = c;
2632  writeIndex += 1;
2633  }
2634 
2635  return true;
2636  }
2637 
2638 
2648  bool ReplaceOpeningStyleTag(ref int[] sourceText, int srcIndex, out int srcOffset, ref int[] charBuffer, ref int writeIndex)
2649  {
2650  // Validate <style> tag.
2651  int hashCode = GetTagHashCode(ref sourceText, srcIndex + 7, out srcOffset);
2652 
2653  TMP_Style style = TMP_StyleSheet.GetStyle(hashCode);
2654 
2655  // Return if we don't have a valid style.
2656  if (style == null || srcOffset == 0) return false;
2657 
2658  m_styleStack.Add(style.hashCode);
2659 
2660  int styleLength = style.styleOpeningTagArray.Length;
2661 
2662  // Replace <style> tag with opening definition
2663  int[] openingTagArray = style.styleOpeningTagArray;
2664 
2665  for (int i = 0; i < styleLength; i++)
2666  {
2667  int c = openingTagArray[i];
2668 
2669  if (c == 60)
2670  {
2671  if (IsTagName(ref openingTagArray, "<BR>", i))
2672  {
2673  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2674 
2675  charBuffer[writeIndex] = 10;
2676  writeIndex += 1;
2677  i += 3;
2678 
2679  continue;
2680  }
2681  else if (IsTagName(ref openingTagArray, "<STYLE=", i))
2682  {
2683  int offset = 0;
2684  if (ReplaceOpeningStyleTag(ref openingTagArray, i, out offset, ref charBuffer, ref writeIndex))
2685  {
2686  i = offset;
2687  continue;
2688  }
2689  }
2690  else if (IsTagName(ref openingTagArray, "</STYLE>", i))
2691  {
2692  ReplaceClosingStyleTag(ref openingTagArray, i, ref charBuffer, ref writeIndex);
2693 
2694  // Strip </style> even if style is invalid.
2695  i += 7;
2696  continue;
2697  }
2698  }
2699 
2700  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2701 
2702  charBuffer[writeIndex] = c;
2703  writeIndex += 1;
2704  }
2705 
2706  return true;
2707  }
2708 
2709 
2719  bool ReplaceOpeningStyleTag(ref char[] sourceText, int srcIndex, out int srcOffset, ref int[] charBuffer, ref int writeIndex)
2720  {
2721  // Validate <style> tag.
2722  int hashCode = GetTagHashCode(ref sourceText, srcIndex + 7, out srcOffset);
2723 
2724  TMP_Style style = TMP_StyleSheet.GetStyle(hashCode);
2725 
2726  // Return if we don't have a valid style.
2727  if (style == null || srcOffset == 0) return false;
2728 
2729  m_styleStack.Add(style.hashCode);
2730 
2731  int styleLength = style.styleOpeningTagArray.Length;
2732 
2733  // Replace <style> tag with opening definition
2734  int[] openingTagArray = style.styleOpeningTagArray;
2735 
2736  for (int i = 0; i < styleLength; i++)
2737  {
2738  int c = openingTagArray[i];
2739 
2740  if (c == 60)
2741  {
2742  if (IsTagName(ref openingTagArray, "<BR>", i))
2743  {
2744  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2745 
2746  charBuffer[writeIndex] = 10;
2747  writeIndex += 1;
2748  i += 3;
2749 
2750  continue;
2751  }
2752  else if (IsTagName(ref openingTagArray, "<STYLE=", i))
2753  {
2754  int offset = 0;
2755  if (ReplaceOpeningStyleTag(ref openingTagArray, i, out offset, ref charBuffer, ref writeIndex))
2756  {
2757  i = offset;
2758  continue;
2759  }
2760  }
2761  else if (IsTagName(ref openingTagArray, "</STYLE>", i))
2762  {
2763  ReplaceClosingStyleTag(ref openingTagArray, i, ref charBuffer, ref writeIndex);
2764 
2765  // Strip </style> even if style is invalid.
2766  i += 7;
2767  continue;
2768  }
2769  }
2770 
2771  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2772 
2773  charBuffer[writeIndex] = c;
2774  writeIndex += 1;
2775  }
2776 
2777  return true;
2778  }
2779 
2780 
2790  bool ReplaceOpeningStyleTag(ref StringBuilder sourceText, int srcIndex, out int srcOffset, ref int[] charBuffer, ref int writeIndex)
2791  {
2792  // Validate <style> tag.
2793  int hashCode = GetTagHashCode(ref sourceText, srcIndex + 7, out srcOffset);
2794 
2795  TMP_Style style = TMP_StyleSheet.GetStyle(hashCode);
2796 
2797  // Return if we don't have a valid style.
2798  if (style == null || srcOffset == 0) return false;
2799 
2800  m_styleStack.Add(style.hashCode);
2801 
2802  int styleLength = style.styleOpeningTagArray.Length;
2803 
2804  // Replace <style> tag with opening definition
2805  int[] openingTagArray = style.styleOpeningTagArray;
2806 
2807  for (int i = 0; i < styleLength; i++)
2808  {
2809  int c = openingTagArray[i];
2810 
2811  if (c == 60)
2812  {
2813  if (IsTagName(ref openingTagArray, "<BR>", i))
2814  {
2815  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2816 
2817  charBuffer[writeIndex] = 10;
2818  writeIndex += 1;
2819  i += 3;
2820 
2821  continue;
2822  }
2823  else if (IsTagName(ref openingTagArray, "<STYLE=", i))
2824  {
2825  int offset = 0;
2826  if (ReplaceOpeningStyleTag(ref openingTagArray, i, out offset, ref charBuffer, ref writeIndex))
2827  {
2828  i = offset;
2829  continue;
2830  }
2831  }
2832  else if (IsTagName(ref openingTagArray, "</STYLE>", i))
2833  {
2834  ReplaceClosingStyleTag(ref openingTagArray, i, ref charBuffer, ref writeIndex);
2835 
2836  // Strip </style> even if style is invalid.
2837  i += 7;
2838  continue;
2839  }
2840  }
2841 
2842  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2843 
2844  charBuffer[writeIndex] = c;
2845  writeIndex += 1;
2846  }
2847 
2848  return true;
2849  }
2850 
2851 
2860  bool ReplaceClosingStyleTag(ref string sourceText, int srcIndex, ref int[] charBuffer, ref int writeIndex)
2861  {
2862  // Get style from the Style Stack
2863  int hashCode = m_styleStack.CurrentItem();
2864  TMP_Style style = TMP_StyleSheet.GetStyle(hashCode);
2865 
2866  m_styleStack.Remove();
2867 
2868  // Return if we don't have a valid style.
2869  if (style == null) return false;
2870 
2871  int styleLength = style.styleClosingTagArray.Length;
2872 
2873  // Replace <style> tag with opening definition
2874  int[] closingTagArray = style.styleClosingTagArray;
2875 
2876  for (int i = 0; i < styleLength; i++)
2877  {
2878  int c = closingTagArray[i];
2879 
2880  if (c == 60)
2881  {
2882  if (IsTagName(ref closingTagArray, "<BR>", i))
2883  {
2884  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2885 
2886  charBuffer[writeIndex] = 10;
2887  writeIndex += 1;
2888  i += 3;
2889 
2890  continue;
2891  }
2892  else if (IsTagName(ref closingTagArray, "<STYLE=", i))
2893  {
2894  int offset = 0;
2895  if (ReplaceOpeningStyleTag(ref closingTagArray, i, out offset, ref charBuffer, ref writeIndex))
2896  {
2897  i = offset;
2898  continue;
2899  }
2900  }
2901  else if (IsTagName(ref closingTagArray, "</STYLE>", i))
2902  {
2903  ReplaceClosingStyleTag(ref closingTagArray, i, ref charBuffer, ref writeIndex);
2904 
2905  // Strip </style> even if style is invalid.
2906  i += 7;
2907  continue;
2908  }
2909  }
2910 
2911  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2912 
2913  charBuffer[writeIndex] = c;
2914  writeIndex += 1;
2915  }
2916 
2917  return true;
2918  }
2919 
2920 
2929  bool ReplaceClosingStyleTag(ref int[] sourceText, int srcIndex, ref int[] charBuffer, ref int writeIndex)
2930  {
2931  // Get style from the Style Stack
2932  int hashCode = m_styleStack.CurrentItem();
2933  TMP_Style style = TMP_StyleSheet.GetStyle(hashCode);
2934 
2935  m_styleStack.Remove();
2936 
2937  // Return if we don't have a valid style.
2938  if (style == null) return false;
2939 
2940  int styleLength = style.styleClosingTagArray.Length;
2941 
2942  // Replace <style> tag with opening definition
2943  int[] closingTagArray = style.styleClosingTagArray;
2944 
2945  for (int i = 0; i < styleLength; i++)
2946  {
2947  int c = closingTagArray[i];
2948 
2949  if (c == 60)
2950  {
2951  if (IsTagName(ref closingTagArray, "<BR>", i))
2952  {
2953  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2954 
2955  charBuffer[writeIndex] = 10;
2956  writeIndex += 1;
2957  i += 3;
2958 
2959  continue;
2960  }
2961  else if (IsTagName(ref closingTagArray, "<STYLE=", i))
2962  {
2963  int offset = 0;
2964  if (ReplaceOpeningStyleTag(ref closingTagArray, i, out offset, ref charBuffer, ref writeIndex))
2965  {
2966  i = offset;
2967  continue;
2968  }
2969  }
2970  else if (IsTagName(ref closingTagArray, "</STYLE>", i))
2971  {
2972  ReplaceClosingStyleTag(ref closingTagArray, i, ref charBuffer, ref writeIndex);
2973 
2974  // Strip </style> even if style is invalid.
2975  i += 7;
2976  continue;
2977  }
2978  }
2979 
2980  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
2981 
2982  charBuffer[writeIndex] = c;
2983  writeIndex += 1;
2984  }
2985 
2986  return true;
2987  }
2988 
2989 
2998  bool ReplaceClosingStyleTag(ref char[] sourceText, int srcIndex, ref int[] charBuffer, ref int writeIndex)
2999  {
3000  // Get style from the Style Stack
3001  int hashCode = m_styleStack.CurrentItem();
3002  TMP_Style style = TMP_StyleSheet.GetStyle(hashCode);
3003 
3004  m_styleStack.Remove();
3005 
3006  // Return if we don't have a valid style.
3007  if (style == null) return false;
3008 
3009  int styleLength = style.styleClosingTagArray.Length;
3010 
3011  // Replace <style> tag with opening definition
3012  int[] closingTagArray = style.styleClosingTagArray;
3013 
3014  for (int i = 0; i < styleLength; i++)
3015  {
3016  int c = closingTagArray[i];
3017 
3018  if (c == 60)
3019  {
3020  if (IsTagName(ref closingTagArray, "<BR>", i))
3021  {
3022  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
3023 
3024  charBuffer[writeIndex] = 10;
3025  writeIndex += 1;
3026  i += 3;
3027 
3028  continue;
3029  }
3030  else if (IsTagName(ref closingTagArray, "<STYLE=", i))
3031  {
3032  int offset = 0;
3033  if (ReplaceOpeningStyleTag(ref closingTagArray, i, out offset, ref charBuffer, ref writeIndex))
3034  {
3035  i = offset;
3036  continue;
3037  }
3038  }
3039  else if (IsTagName(ref closingTagArray, "</STYLE>", i))
3040  {
3041  ReplaceClosingStyleTag(ref closingTagArray, i, ref charBuffer, ref writeIndex);
3042 
3043  // Strip </style> even if style is invalid.
3044  i += 7;
3045  continue;
3046  }
3047  }
3048 
3049  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
3050 
3051  charBuffer[writeIndex] = c;
3052  writeIndex += 1;
3053  }
3054 
3055  return true;
3056  }
3057 
3066  bool ReplaceClosingStyleTag(ref StringBuilder sourceText, int srcIndex, ref int[] charBuffer, ref int writeIndex)
3067  {
3068  // Get style from the Style Stack
3069  int hashCode = m_styleStack.CurrentItem();
3070  TMP_Style style = TMP_StyleSheet.GetStyle(hashCode);
3071 
3072  m_styleStack.Remove();
3073 
3074  // Return if we don't have a valid style.
3075  if (style == null) return false;
3076 
3077  int styleLength = style.styleClosingTagArray.Length;
3078 
3079  // Replace <style> tag with opening definition
3080  int[] closingTagArray = style.styleClosingTagArray;
3081 
3082  for (int i = 0; i < styleLength; i++)
3083  {
3084  int c = closingTagArray[i];
3085 
3086  if (c == 60)
3087  {
3088  if (IsTagName(ref closingTagArray, "<BR>", i))
3089  {
3090  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
3091 
3092  charBuffer[writeIndex] = 10;
3093  writeIndex += 1;
3094  i += 3;
3095 
3096  continue;
3097  }
3098  else if (IsTagName(ref closingTagArray, "<STYLE=", i))
3099  {
3100  int offset = 0;
3101  if (ReplaceOpeningStyleTag(ref closingTagArray, i, out offset, ref charBuffer, ref writeIndex))
3102  {
3103  i = offset;
3104  continue;
3105  }
3106  }
3107  else if (IsTagName(ref closingTagArray, "</STYLE>", i))
3108  {
3109  ReplaceClosingStyleTag(ref closingTagArray, i, ref charBuffer, ref writeIndex);
3110 
3111  // Strip </style> even if style is invalid.
3112  i += 7;
3113  continue;
3114  }
3115  }
3116 
3117  if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
3118 
3119  charBuffer[writeIndex] = c;
3120  writeIndex += 1;
3121  }
3122 
3123  return true;
3124  }
3125 
3126 
3134  bool IsTagName (ref string text, string tag, int index)
3135  {
3136  if (text.Length < index + tag.Length) return false;
3137 
3138  for (int i = 0; i < tag.Length; i++)
3139  {
3140  if (TMP_TextUtilities.ToUpperFast(text[index + i]) != tag[i]) return false;
3141  }
3142 
3143  return true;
3144  }
3145 
3153  bool IsTagName(ref char[] text, string tag, int index)
3154  {
3155  if (text.Length < index + tag.Length) return false;
3156 
3157  for (int i = 0; i < tag.Length; i++)
3158  {
3159  if (TMP_TextUtilities.ToUpperFast(text[index + i]) != tag[i]) return false;
3160  }
3161 
3162  return true;
3163  }
3164 
3172  bool IsTagName(ref int[] text, string tag, int index)
3173  {
3174  if (text.Length < index + tag.Length) return false;
3175 
3176  for (int i = 0; i < tag.Length; i++)
3177  {
3178  if (TMP_TextUtilities.ToUpperFast((char)text[index + i]) != tag[i]) return false;
3179  }
3180 
3181  return true;
3182  }
3183 
3191  bool IsTagName(ref StringBuilder text, string tag, int index)
3192  {
3193  if (text.Length < index + tag.Length) return false;
3194 
3195  for (int i = 0; i < tag.Length; i++)
3196  {
3197  if (TMP_TextUtilities.ToUpperFast(text[index + i]) != tag[i]) return false;
3198  }
3199 
3200  return true;
3201  }
3202 
3210  int GetTagHashCode(ref string text, int index, out int closeIndex)
3211  {
3212  int hashCode = 0;
3213  closeIndex = 0;
3214 
3215  for (int i = index; i < text.Length; i++)
3216  {
3217  // Skip quote '"' character
3218  if (text[i] == 34) continue;
3219 
3220  // Break at '>'
3221  if (text[i] == 62) { closeIndex = i; break; }
3222 
3223  hashCode = (hashCode << 5) + hashCode ^ text[i];
3224  }
3225 
3226  return hashCode;
3227  }
3228 
3236  int GetTagHashCode(ref char[] text, int index, out int closeIndex)
3237  {
3238  int hashCode = 0;
3239  closeIndex = 0;
3240 
3241  for (int i = index; i < text.Length; i++)
3242  {
3243  // Skip quote '"' character
3244  if (text[i] == 34) continue;
3245 
3246  // Break at '>'
3247  if (text[i] == 62) { closeIndex = i; break; }
3248 
3249  hashCode = (hashCode << 5) + hashCode ^ text[i];
3250  }
3251 
3252  return hashCode;
3253  }
3254 
3262  int GetTagHashCode(ref int[] text, int index, out int closeIndex)
3263  {
3264  int hashCode = 0;
3265  closeIndex = 0;
3266 
3267  for (int i = index; i < text.Length; i++)
3268  {
3269  // Skip quote '"' character
3270  if (text[i] == 34) continue;
3271 
3272  // Break at '>'
3273  if (text[i] == 62) { closeIndex = i; break; }
3274 
3275  hashCode = (hashCode << 5) + hashCode ^ text[i];
3276  }
3277 
3278  return hashCode;
3279  }
3280 
3288  int GetTagHashCode(ref StringBuilder text, int index, out int closeIndex)
3289  {
3290  int hashCode = 0;
3291  closeIndex = 0;
3292 
3293  for (int i = index; i < text.Length; i++)
3294  {
3295  // Skip quote '"' character
3296  if (text[i] == 34) continue;
3297 
3298  // Break at '>'
3299  if (text[i] == 62) { closeIndex = i; break; }
3300 
3301  hashCode = (hashCode << 5) + hashCode ^ text[i];
3302  }
3303 
3304  return hashCode;
3305  }
3306 
3310  void ResizeInternalArray <T>(ref T[] array)
3311  {
3312  int size = Mathf.NextPowerOfTwo(array.Length + 1);
3313 
3314  System.Array.Resize(ref array, size);
3315  }
3316 
3317 
3318  private readonly float[] k_Power = { 5e-1f, 5e-2f, 5e-3f, 5e-4f, 5e-5f, 5e-6f, 5e-7f, 5e-8f, 5e-9f, 5e-10f }; // Used by FormatText to enable rounding and avoid using Mathf.Pow.
3319 
3326  protected void AddFloatToCharArray(float number, ref int index, int precision)
3327  {
3328  if (number < 0)
3329  {
3330  m_input_CharArray[index++] = '-';
3331  number = -number;
3332  }
3333 
3334  number += k_Power[Mathf.Min(9, precision)];
3335 
3336  int integer = (int)number;
3337  AddIntToCharArray(integer, ref index, precision);
3338 
3339  if (precision > 0)
3340  {
3341  // Add the decimal point
3342  m_input_CharArray[index++] = '.';
3343 
3344  number -= integer;
3345  for (int p = 0; p < precision; p++)
3346  {
3347  number *= 10;
3348  int d = (int)(number);
3349 
3350  m_input_CharArray[index++] = (char)(d + 48);
3351  number -= d;
3352  }
3353  }
3354  }
3355 
3356 
3363  protected void AddIntToCharArray(int number, ref int index, int precision)
3364  {
3365  if (number < 0)
3366  {
3367  m_input_CharArray[index++] = '-';
3368  number = -number;
3369  }
3370 
3371  int i = index;
3372  do
3373  {
3374  m_input_CharArray[i++] = (char)(number % 10 + 48);
3375  number /= 10;
3376  } while (number > 0);
3377 
3378  int lastIndex = i;
3379 
3380  // Reverse string
3381  while (index + 1 < i)
3382  {
3383  i -= 1;
3384  char t = m_input_CharArray[index];
3385  m_input_CharArray[index] = m_input_CharArray[i];
3386  m_input_CharArray[i] = t;
3387  index += 1;
3388  }
3389  index = lastIndex;
3390  }
3391 
3392 
3398  protected virtual int SetArraySizes(int[] chars) { return 0; }
3399 
3400 
3404  protected virtual void GenerateTextMesh() { }
3405 
3406 
3411  public Vector2 GetPreferredValues()
3412  {
3413  if (m_isInputParsingRequired || m_isTextTruncated)
3414  {
3415  m_isCalculatingPreferredValues = true;
3416  ParseInputText();
3417  }
3418 
3419  // CALCULATE PREFERRED WIDTH
3421 
3422  // CALCULATE PREFERRED HEIGHT
3424 
3425  return new Vector2(preferredWidth, preferredHeight);
3426  }
3427 
3428 
3433  public Vector2 GetPreferredValues(float width, float height)
3434  {
3435  if (m_isInputParsingRequired || m_isTextTruncated)
3436  {
3437  m_isCalculatingPreferredValues = true;
3438  ParseInputText();
3439  }
3440 
3441  Vector2 margin = new Vector2(width, height);
3442 
3443  // CALCULATE PREFERRED WIDTH
3445 
3446  // CALCULATE PREFERRED HEIGHT
3448 
3449  return new Vector2(preferredWidth, preferredHeight);
3450  }
3451 
3452 
3458  public Vector2 GetPreferredValues(string text)
3459  {
3460  m_isCalculatingPreferredValues = true;
3461 
3462  StringToCharArray(text, ref m_char_buffer);
3463  SetArraySizes(m_char_buffer);
3464 
3465  Vector2 margin = k_LargePositiveVector2;
3466 
3467  // CALCULATE PREFERRED WIDTH
3469 
3470  // CALCULATE PREFERRED HEIGHT
3472 
3473  return new Vector2(preferredWidth, preferredHeight);
3474  }
3475 
3476 
3482  public Vector2 GetPreferredValues(string text, float width, float height)
3483  {
3484  m_isCalculatingPreferredValues = true;
3485 
3486  StringToCharArray(text, ref m_char_buffer);
3487  SetArraySizes(m_char_buffer);
3488 
3489  Vector2 margin = new Vector2(width, height);
3490 
3491  // CALCULATE PREFERRED WIDTH
3493 
3494  // CALCULATE PREFERRED HEIGHT
3496 
3497  return new Vector2(preferredWidth, preferredHeight);
3498  }
3499 
3500 
3505  protected float GetPreferredWidth()
3506  {
3507  if (TMP_Settings.instance == null) return 0;
3508 
3509  float fontSize = m_enableAutoSizing ? m_fontSizeMax : m_fontSize;
3510 
3511  // Reset auto sizing point size bounds
3512  m_minFontSize = m_fontSizeMin;
3513  m_maxFontSize = m_fontSizeMax;
3514  m_charWidthAdjDelta = 0;
3515 
3516  // Set Margins to Infinity
3517  Vector2 margin = k_LargePositiveVector2;
3518 
3519  if (m_isInputParsingRequired || m_isTextTruncated)
3520  {
3521  m_isCalculatingPreferredValues = true;
3522  ParseInputText();
3523  }
3524 
3525  m_recursiveCount = 0;
3527 
3528  m_isPreferredWidthDirty = false;
3529 
3530  //Debug.Log("GetPreferredWidth() Called at frame " + Time.frameCount + ". Returning width of " + preferredWidth);
3531 
3532  return preferredWidth;
3533  }
3534 
3535 
3541  protected float GetPreferredWidth(Vector2 margin)
3542  {
3543  float fontSize = m_enableAutoSizing ? m_fontSizeMax : m_fontSize;
3544 
3545  // Reset auto sizing point size bounds
3546  m_minFontSize = m_fontSizeMin;
3547  m_maxFontSize = m_fontSizeMax;
3548  m_charWidthAdjDelta = 0;
3549 
3550  m_recursiveCount = 0;
3552 
3553  //Debug.Log("GetPreferredWidth() Called. Returning width of " + preferredWidth);
3554 
3555  return preferredWidth;
3556  }
3557 
3558 
3563  protected float GetPreferredHeight()
3564  {
3565  if (TMP_Settings.instance == null) return 0;
3566 
3567  float fontSize = m_enableAutoSizing ? m_fontSizeMax : m_fontSize;
3568 
3569  // Reset auto sizing point size bounds
3570  m_minFontSize = m_fontSizeMin;
3571  m_maxFontSize = m_fontSizeMax;
3572  m_charWidthAdjDelta = 0;
3573 
3574  Vector2 margin = new Vector2(m_marginWidth != 0 ? m_marginWidth : k_LargePositiveFloat, k_LargePositiveFloat);
3575 
3576  if (m_isInputParsingRequired || m_isTextTruncated)
3577  {
3578  m_isCalculatingPreferredValues = true;
3579  ParseInputText();
3580  }
3581 
3582  m_recursiveCount = 0;
3583  float preferredHeight = CalculatePreferredValues(fontSize, margin, !m_enableAutoSizing).y;
3584 
3585  m_isPreferredHeightDirty = false;
3586 
3587  //Debug.Log("GetPreferredHeight() Called. Returning height of " + preferredHeight);
3588 
3589  return preferredHeight;
3590  }
3591 
3592 
3598  protected float GetPreferredHeight(Vector2 margin)
3599  {
3600  float fontSize = m_enableAutoSizing ? m_fontSizeMax : m_fontSize;
3601 
3602  // Reset auto sizing point size bounds
3603  m_minFontSize = m_fontSizeMin;
3604  m_maxFontSize = m_fontSizeMax;
3605  m_charWidthAdjDelta = 0;
3606 
3607  m_recursiveCount = 0;
3609 
3610  //Debug.Log("GetPreferredHeight() Called. Returning height of " + preferredHeight);
3611 
3612  return preferredHeight;
3613  }
3614 
3615 
3620  public Vector2 GetRenderedValues()
3621  {
3622  return GetTextBounds().size;
3623  }
3624 
3630  public Vector2 GetRenderedValues(bool onlyVisibleCharacters)
3631  {
3632  return GetTextBounds(onlyVisibleCharacters).size;
3633  }
3634 
3635 
3640  protected float GetRenderedWidth()
3641  {
3642  return GetRenderedValues().x;
3643  }
3644 
3649  protected float GetRenderedWidth(bool onlyVisibleCharacters)
3650  {
3651  return GetRenderedValues(onlyVisibleCharacters).x;
3652  }
3653 
3658  protected float GetRenderedHeight()
3659  {
3660  return GetRenderedValues().y;
3661  }
3662 
3667  protected float GetRenderedHeight(bool onlyVisibleCharacters)
3668  {
3669  return GetRenderedValues(onlyVisibleCharacters).y;
3670  }
3671 
3672 
3677  protected virtual Vector2 CalculatePreferredValues(float defaultFontSize, Vector2 marginSize, bool ignoreTextAutoSizing)
3678  {
3679  //Debug.Log("*** CalculatePreferredValues() ***"); // ***** Frame: " + Time.frameCount);
3680 
3682 
3683  // Early exit if no font asset was assigned. This should not be needed since LiberationSans SDF will be assigned by default.
3684  if (m_fontAsset == null || m_fontAsset.characterDictionary == null)
3685  {
3686  Debug.LogWarning("Can't Generate Mesh! No Font Asset has been assigned to Object ID: " + this.GetInstanceID());
3687 
3688  return Vector2.zero;
3689  }
3690 
3691  // Early exit if we don't have any Text to generate.
3692  if (m_char_buffer == null || m_char_buffer.Length == 0 || m_char_buffer[0] == (char)0)
3693  {
3694  return Vector2.zero;
3695  }
3696 
3697  m_currentFontAsset = m_fontAsset;
3698  m_currentMaterial = m_sharedMaterial;
3699  m_currentMaterialIndex = 0;
3700  m_materialReferenceStack.SetDefault(new MaterialReference(0, m_currentFontAsset, null, m_currentMaterial, m_padding));
3701 
3702  // Total character count is computed when the text is parsed.
3703  int totalCharacterCount = m_totalCharacterCount; // m_VisibleCharacters.Count;
3704 
3705  if (m_internalCharacterInfo == null || totalCharacterCount > m_internalCharacterInfo.Length)
3706  {
3707  m_internalCharacterInfo = new TMP_CharacterInfo[totalCharacterCount > 1024 ? totalCharacterCount + 256 : Mathf.NextPowerOfTwo(totalCharacterCount)];
3708  }
3709 
3710  // Calculate the scale of the font based on selected font size and sampling point size.
3711  // baseScale is calculated using the font asset assigned to the text object.
3712  float baseScale = m_fontScale = (defaultFontSize / m_fontAsset.fontInfo.PointSize * m_fontAsset.fontInfo.Scale * (m_isOrthographic ? 1 : 0.1f));
3713  float currentElementScale = baseScale;
3714  m_fontScaleMultiplier = 1;
3715 
3716  m_currentFontSize = defaultFontSize;
3717  m_sizeStack.SetDefault(m_currentFontSize);
3718  float fontSizeDelta = 0;
3719 
3720  int charCode = 0; // Holds the character code of the currently being processed character.
3721 
3722  m_style = m_fontStyle; // Set the default style.
3723 
3724  m_lineJustification = m_textAlignment; // Sets the line justification mode to match editor alignment.
3725  m_lineJustificationStack.SetDefault(m_lineJustification);
3726 
3727  float bold_xAdvance_multiplier = 1; // Used to increase spacing between character when style is bold.
3728 
3729  m_baselineOffset = 0; // Used by subscript characters.
3730  m_baselineOffsetStack.Clear();
3731 
3732  m_lineOffset = 0; // Amount of space between lines (font line spacing + m_linespacing).
3733  m_lineHeight = TMP_Math.FLOAT_UNSET;
3734  float lineGap = m_currentFontAsset.fontInfo.LineHeight - (m_currentFontAsset.fontInfo.Ascender - m_currentFontAsset.fontInfo.Descender);
3735 
3736  m_cSpacing = 0; // Amount of space added between characters as a result of the use of the <cspace> tag.
3737  m_monoSpacing = 0;
3738  float lineOffsetDelta = 0;
3739  m_xAdvance = 0; // Used to track the position of each character.
3740  float maxXAdvance = 0; // Used to determine Preferred Width.
3741 
3742  tag_LineIndent = 0; // Used for indentation of text.
3743  tag_Indent = 0;
3744  m_indentStack.SetDefault(0);
3745  tag_NoParsing = false;
3746  //m_isIgnoringAlignment = false;
3747 
3748  m_characterCount = 0; // Total characters in the char[]
3749 
3750 
3751  // Tracking of line information
3752  m_firstCharacterOfLine = 0;
3753  m_maxLineAscender = k_LargeNegativeFloat;
3754  m_maxLineDescender = k_LargePositiveFloat;
3755  m_lineNumber = 0;
3756 
3757  float marginWidth = marginSize.x;
3758  //float marginHeight = marginSize.y;
3759  m_marginLeft = 0;
3760  m_marginRight = 0;
3761  m_width = -1;
3762 
3763  // Used by Unity's Auto Layout system.
3764  float renderedWidth = 0;
3765  float renderedHeight = 0;
3766  float linebreakingWidth = 0;
3767  m_isCalculatingPreferredValues = true;
3768 
3769  // Tracking of the highest Ascender
3770  m_maxAscender = 0;
3771  m_maxDescender = 0;
3772 
3773 
3774  // Initialize struct to track states of word wrapping
3775  bool isFirstWord = true;
3776  bool isLastBreakingChar = false;
3777  WordWrapState savedLineState = new WordWrapState();
3778  SaveWordWrappingState(ref savedLineState, 0, 0);
3779  WordWrapState savedWordWrapState = new WordWrapState();
3780  int wrappingIndex = 0;
3781 
3782  // Counter to prevent recursive lockup when computing preferred values.
3783  m_recursiveCount += 1;
3784 
3785  int endTagIndex = 0;
3786  // Parse through Character buffer to read HTML tags and begin creating mesh.
3787  for (int i = 0; m_char_buffer[i] != 0; i++)
3788  {
3789  charCode = m_char_buffer[i];
3790 
3791  // Parse Rich Text Tag
3792  #region Parse Rich Text Tag
3793  if (m_isRichText && charCode == 60) // '<'
3794  {
3795  m_isParsingText = true;
3796  m_textElementType = TMP_TextElementType.Character;
3797 
3798  // Check if Tag is valid. If valid, skip to the end of the validated tag.
3799  if (ValidateHtmlTag(m_char_buffer, i + 1, out endTagIndex))
3800  {
3801  i = endTagIndex;
3802 
3803  // Continue to next character or handle the sprite element
3804  if (m_textElementType == TMP_TextElementType.Character)
3805  continue;
3806  }
3807  }
3808  else
3809  {
3810  m_textElementType = m_textInfo.characterInfo[m_characterCount].elementType;
3811  m_currentMaterialIndex = m_textInfo.characterInfo[m_characterCount].materialReferenceIndex;
3812  m_currentFontAsset = m_textInfo.characterInfo[m_characterCount].fontAsset;
3813  }
3814  #endregion End Parse Rich Text Tag
3815 
3816  int prev_MaterialIndex = m_currentMaterialIndex;
3817  bool isUsingAltTypeface = m_textInfo.characterInfo[m_characterCount].isUsingAlternateTypeface;
3818 
3819  m_isParsingText = false;
3820 
3821  // Handle Font Styles like LowerCase, UpperCase and SmallCaps.
3822  #region Handling of LowerCase, UpperCase and SmallCaps Font Styles
3823 
3824  float smallCapsMultiplier = 1.0f;
3825 
3826  if (m_textElementType == TMP_TextElementType.Character)
3827  {
3828  if ((m_style & FontStyles.UpperCase) == FontStyles.UpperCase)
3829  {
3830  // If this character is lowercase, switch to uppercase.
3831  if (char.IsLower((char)charCode))
3832  charCode = char.ToUpper((char)charCode);
3833 
3834  }
3835  else if ((m_style & FontStyles.LowerCase) == FontStyles.LowerCase)
3836  {
3837  // If this character is uppercase, switch to lowercase.
3838  if (char.IsUpper((char)charCode))
3839  charCode = char.ToLower((char)charCode);
3840  }
3841  else if ((m_fontStyle & FontStyles.SmallCaps) == FontStyles.SmallCaps || (m_style & FontStyles.SmallCaps) == FontStyles.SmallCaps)
3842  {
3843  if (char.IsLower((char)charCode))
3844  {
3845  smallCapsMultiplier = 0.8f;
3846  charCode = char.ToUpper((char)charCode);
3847  }
3848  }
3849  }
3850  #endregion
3851 
3852 
3853  // Look up Character Data from Dictionary and cache it.
3854  #region Look up Character Data
3855  if (m_textElementType == TMP_TextElementType.Sprite)
3856  {
3857  // If a sprite is used as a fallback then get a reference to it and set the color to white.
3858  m_currentSpriteAsset = m_textInfo.characterInfo[m_characterCount].spriteAsset;
3859  m_spriteIndex = m_textInfo.characterInfo[m_characterCount].spriteIndex;
3860 
3861  TMP_Sprite sprite = m_currentSpriteAsset.spriteInfoList[m_spriteIndex];
3862  if (sprite == null) continue;
3863 
3864  // Sprites are assigned in the E000 Private Area + sprite Index
3865  if (charCode == 60)
3866  charCode = 57344 + m_spriteIndex;
3867 
3868  m_currentFontAsset = m_fontAsset;
3869 
3870  // The sprite scale calculations are based on the font asset assigned to the text object.
3871  // Sprite scale is used to determine line height
3872  // Current element scale represents a modified scale to normalize the sprite based on the font baseline to ascender.
3873  float spriteScale = (m_currentFontSize / m_fontAsset.fontInfo.PointSize * m_fontAsset.fontInfo.Scale * (m_isOrthographic ? 1 : 0.1f));
3874  currentElementScale = m_fontAsset.fontInfo.Ascender / sprite.height * sprite.scale * spriteScale;
3875 
3876  m_cached_TextElement = sprite;
3877 
3878  m_internalCharacterInfo[m_characterCount].elementType = TMP_TextElementType.Sprite;
3879  m_internalCharacterInfo[m_characterCount].scale = spriteScale;
3880  //m_internalCharacterInfo[m_characterCount].spriteAsset = m_currentSpriteAsset;
3881  //m_internalCharacterInfo[m_characterCount].fontAsset = m_currentFontAsset;
3882  //m_internalCharacterInfo[m_characterCount].materialReferenceIndex = m_currentMaterialIndex;
3883 
3884  m_currentMaterialIndex = prev_MaterialIndex;
3885  }
3886  else if (m_textElementType == TMP_TextElementType.Character)
3887  {
3888  m_cached_TextElement = m_textInfo.characterInfo[m_characterCount].textElement;
3889  if (m_cached_TextElement == null) continue;
3890 
3891  //m_currentFontAsset = m_textInfo.characterInfo[m_characterCount].fontAsset;
3892  //m_currentMaterial = m_textInfo.characterInfo[m_characterCount].material;
3893  m_currentMaterialIndex = m_textInfo.characterInfo[m_characterCount].materialReferenceIndex;
3894 
3895  // Re-calculate font scale as the font asset may have changed.
3896  m_fontScale = m_currentFontSize * smallCapsMultiplier / m_currentFontAsset.fontInfo.PointSize * m_currentFontAsset.fontInfo.Scale * (m_isOrthographic ? 1 : 0.1f);
3897 
3898  currentElementScale = m_fontScale * m_fontScaleMultiplier * m_cached_TextElement.scale;
3899 
3900  m_internalCharacterInfo[m_characterCount].elementType = TMP_TextElementType.Character;
3901 
3902  }
3903  #endregion
3904 
3905 
3906  // Handle Soft Hyphen
3907  #region Handle Soft Hyphen
3908  float old_scale = currentElementScale;
3909  if (charCode == 0xAD)
3910  {
3911  currentElementScale = 0;
3912  }
3913  #endregion
3914 
3915 
3916  // Store some of the text object's information
3917  m_internalCharacterInfo[m_characterCount].character = (char)charCode;
3918 
3919 
3920  // Handle Kerning if Enabled.
3921  #region Handle Kerning
3922  GlyphValueRecord glyphAdjustments = new GlyphValueRecord();
3923  if (m_enableKerning)
3924  {
3925  KerningPair adjustmentPair = null;
3926 
3927  if (m_characterCount < totalCharacterCount - 1)
3928  {
3929  uint nextGlyph = m_textInfo.characterInfo[m_characterCount + 1].character;
3930  KerningPairKey keyValue = new KerningPairKey((uint)charCode, nextGlyph);
3931 
3932  m_currentFontAsset.kerningDictionary.TryGetValue((int)keyValue.key, out adjustmentPair);
3933  if (adjustmentPair != null)
3934  glyphAdjustments = adjustmentPair.firstGlyphAdjustments;
3935  }
3936 
3937  if (m_characterCount >= 1)
3938  {
3939  uint previousGlyph = m_textInfo.characterInfo[m_characterCount - 1].character;
3940  KerningPairKey keyValue = new KerningPairKey(previousGlyph, (uint)charCode);
3941 
3942  m_currentFontAsset.kerningDictionary.TryGetValue((int)keyValue.key, out adjustmentPair);
3943  if (adjustmentPair != null)
3944  glyphAdjustments += adjustmentPair.secondGlyphAdjustments;
3945  }
3946  }
3947  #endregion
3948 
3949 
3950  // Initial Implementation for RTL support.
3951  #region Handle Right-to-Left
3952  //if (m_isRightToLeft)
3953  //{
3954  // m_xAdvance -= ((m_cached_TextElement.xAdvance * bold_xAdvance_multiplier + m_characterSpacing + m_wordSpacing + m_currentFontAsset.normalSpacingOffset) * currentElementScale + m_cSpacing) * (1 - m_charWidthAdjDelta);
3955 
3956  // if (char.IsWhiteSpace((char)charCode) || charCode == 0x200B)
3957  // m_xAdvance -= m_wordSpacing * currentElementScale;
3958  //}
3959  #endregion
3960 
3961 
3962  // Handle Mono Spacing
3963  #region Handle Mono Spacing
3964  float monoAdvance = 0;
3965  if (m_monoSpacing != 0)
3966  {
3967  monoAdvance = (m_monoSpacing / 2 - (m_cached_TextElement.width / 2 + m_cached_TextElement.xOffset) * currentElementScale);
3968  m_xAdvance += monoAdvance;
3969  }
3970  #endregion
3971 
3972 
3973  // Set Padding based on selected font style
3974  #region Handle Style Padding
3975  if (m_textElementType == TMP_TextElementType.Character && !isUsingAltTypeface && ((m_style & FontStyles.Bold) == FontStyles.Bold || (m_fontStyle & FontStyles.Bold) == FontStyles.Bold)) // Checks for any combination of Bold Style.
3976  {
3977  //style_padding = m_currentFontAsset.boldStyle * 2;
3978  bold_xAdvance_multiplier = 1 + m_currentFontAsset.boldSpacing * 0.01f;
3979  }
3980  else
3981  {
3982  //style_padding = m_currentFontAsset.normalStyle * 2;
3983  bold_xAdvance_multiplier = 1.0f;
3984  }
3985  #endregion Handle Style Padding
3986 
3987  m_internalCharacterInfo[m_characterCount].baseLine = 0 - m_lineOffset + m_baselineOffset;
3988 
3989 
3990  // Compute and save text element Ascender and maximum line Ascender.
3991  float elementAscender = m_currentFontAsset.fontInfo.Ascender * (m_textElementType == TMP_TextElementType.Character ? currentElementScale / smallCapsMultiplier : m_internalCharacterInfo[m_characterCount].scale) + m_baselineOffset;
3992  m_internalCharacterInfo[m_characterCount].ascender = elementAscender - m_lineOffset;
3993  m_maxLineAscender = elementAscender > m_maxLineAscender ? elementAscender : m_maxLineAscender;
3994 
3995  // Compute and save text element Descender and maximum line Descender.
3996  float elementDescender = m_currentFontAsset.fontInfo.Descender * (m_textElementType == TMP_TextElementType.Character ? currentElementScale / smallCapsMultiplier: m_internalCharacterInfo[m_characterCount].scale) + m_baselineOffset;
3997  float elementDescenderII = m_internalCharacterInfo[m_characterCount].descender = elementDescender - m_lineOffset;
3998  m_maxLineDescender = elementDescender < m_maxLineDescender ? elementDescender : m_maxLineDescender;
3999 
4000  // Adjust maxLineAscender and maxLineDescender if style is superscript or subscript
4001  if ((m_style & FontStyles.Subscript) == FontStyles.Subscript || (m_style & FontStyles.Superscript) == FontStyles.Superscript)
4002  {
4003  float baseAscender = (elementAscender - m_baselineOffset) / m_currentFontAsset.fontInfo.SubSize;
4004  elementAscender = m_maxLineAscender;
4005  m_maxLineAscender = baseAscender > m_maxLineAscender ? baseAscender : m_maxLineAscender;
4006 
4007  float baseDescender = (elementDescender - m_baselineOffset) / m_currentFontAsset.fontInfo.SubSize;
4008  elementDescender = m_maxLineDescender;
4009  m_maxLineDescender = baseDescender < m_maxLineDescender ? baseDescender : m_maxLineDescender;
4010  }
4011 
4012  if (m_lineNumber == 0) m_maxAscender = m_maxAscender > elementAscender ? m_maxAscender : elementAscender;
4013  //if (m_lineOffset == 0) pageAscender = pageAscender > elementAscender ? pageAscender : elementAscender;
4014 
4015  // Setup Mesh for visible text elements. ie. not a SPACE / LINEFEED / CARRIAGE RETURN.
4016  #region Handle Visible Characters
4017  if (charCode == 9 || charCode == 0xA0 || charCode == 0x2007 || (!char.IsWhiteSpace((char)charCode) && charCode != 0x200B) || m_textElementType == TMP_TextElementType.Sprite)
4018  {
4019  // Check if Character exceeds the width of the Text Container
4020  #region Handle Line Breaking, Text Auto-Sizing and Horizontal Overflow
4021  float width = m_width != -1 ? Mathf.Min(marginWidth + 0.0001f - m_marginLeft - m_marginRight, m_width) : marginWidth + 0.0001f - m_marginLeft - m_marginRight;
4022 
4023  bool isJustifiedOrFlush = ((_HorizontalAlignmentOptions)m_lineJustification & _HorizontalAlignmentOptions.Flush) == _HorizontalAlignmentOptions.Flush || ((_HorizontalAlignmentOptions)m_lineJustification & _HorizontalAlignmentOptions.Justified) == _HorizontalAlignmentOptions.Justified;
4024 
4025  // Calculate the line breaking width of the text.
4026  linebreakingWidth = m_xAdvance + m_cached_TextElement.xAdvance * (1 - m_charWidthAdjDelta) * (charCode != 0xAD ? currentElementScale : old_scale);
4027 
4028  // Check if Character exceeds the width of the Text Container
4029  if (linebreakingWidth > width * (isJustifiedOrFlush ? 1.05f : 1.0f))
4030  {
4031  // Word Wrapping
4032  #region Handle Word Wrapping
4033  if (enableWordWrapping && m_characterCount != m_firstCharacterOfLine)
4034  {
4035  // Check if word wrapping is still possible
4036  #region Line Breaking Check
4037  if (wrappingIndex == savedWordWrapState.previous_WordBreak || isFirstWord)
4038  {
4039  // Word wrapping is no longer possible. Shrink size of text if auto-sizing is enabled.
4040  #region Text Auto-Sizing
4041  if (ignoreTextAutoSizing == false && m_currentFontSize > m_fontSizeMin)
4042  {
4043  // Handle Character Width Adjustments
4044  #region Character Width Adjustments
4045  if (m_charWidthAdjDelta < m_charWidthMaxAdj / 100)
4046  {
4047  m_recursiveCount = 0;
4048  m_charWidthAdjDelta += 0.01f;
4049  return CalculatePreferredValues(defaultFontSize, marginSize, false);
4050  }
4051  #endregion
4052 
4053  // Adjust Point Size
4054  m_maxFontSize = defaultFontSize;
4055 
4056  defaultFontSize -= Mathf.Max((defaultFontSize - m_minFontSize) / 2, 0.05f);
4057  defaultFontSize = (int)(Mathf.Max(defaultFontSize, m_fontSizeMin) * 20 + 0.5f) / 20f;
4058 
4059  if (m_recursiveCount > 20) return new Vector2(renderedWidth, renderedHeight);
4060  return CalculatePreferredValues(defaultFontSize, marginSize, false);
4061  }
4062  #endregion
4063 
4064  // Word wrapping is no longer possible, now breaking up individual words.
4065  if (m_isCharacterWrappingEnabled == false)
4066  {
4067  m_isCharacterWrappingEnabled = true;
4068  }
4069  else
4070  isLastBreakingChar = true;
4071  }
4072  #endregion
4073 
4074  // Restore to previously stored state of last valid (space character or linefeed)
4075  i = RestoreWordWrappingState(ref savedWordWrapState);
4076  wrappingIndex = i; // Used to detect when line length can no longer be reduced.
4077 
4078  // Handling for Soft Hyphen
4079  if (m_char_buffer[i] == 0xAD) // && !m_isCharacterWrappingEnabled) // && ellipsisIndex != i && !m_isCharacterWrappingEnabled)
4080  {
4081  m_isTextTruncated = true;
4082  m_char_buffer[i] = 0x2D;
4083  return CalculatePreferredValues(defaultFontSize, marginSize, true);
4084  }
4085 
4086  // Check if Line Spacing of previous line needs to be adjusted.
4087  if (m_lineNumber > 0 && !TMP_Math.Approximately(m_maxLineAscender, m_startOfLineAscender) && m_lineHeight == TMP_Math.FLOAT_UNSET)
4088  {
4089  //Debug.Log("(1) Adjusting Line Spacing on line #" + m_lineNumber);
4090  float offsetDelta = m_maxLineAscender - m_startOfLineAscender;
4091  //AdjustLineOffset(m_firstCharacterOfLine, m_characterCount, offsetDelta);
4092  m_lineOffset += offsetDelta;
4093  savedWordWrapState.lineOffset = m_lineOffset;
4094  savedWordWrapState.previousLineAscender = m_maxLineAscender;
4095 
4096  // TODO - Add check for character exceeding vertical bounds
4097  }
4098  //m_isNewPage = false;
4099 
4100  // Calculate lineAscender & make sure if last character is superscript or subscript that we check that as well.
4101  float lineAscender = m_maxLineAscender - m_lineOffset;
4102  float lineDescender = m_maxLineDescender - m_lineOffset;
4103 
4104 
4105  // Update maxDescender and maxVisibleDescender
4106  m_maxDescender = m_maxDescender < lineDescender ? m_maxDescender : lineDescender;
4107 
4108 
4109  m_firstCharacterOfLine = m_characterCount; // Store first character of the next line.
4110 
4111  // Compute Preferred Width & Height
4112  renderedWidth += m_xAdvance;
4113 
4114  if (m_enableWordWrapping)
4115  renderedHeight = m_maxAscender - m_maxDescender;
4116  else
4117  renderedHeight = Mathf.Max(renderedHeight, lineAscender - lineDescender);
4118 
4119 
4120  // Store the state of the line before starting on the new line.
4121  SaveWordWrappingState(ref savedLineState, i, m_characterCount - 1);
4122 
4123  m_lineNumber += 1;
4124  //isStartOfNewLine = true;
4125 
4126  // Check to make sure Array is large enough to hold a new line.
4127  //if (m_lineNumber >= m_internalTextInfo.lineInfo.Length)
4128  // ResizeLineExtents(m_lineNumber);
4129 
4130  // Apply Line Spacing based on scale of the last character of the line.
4131  if (m_lineHeight == TMP_Math.FLOAT_UNSET)
4132  {
4133  float ascender = m_internalCharacterInfo[m_characterCount].ascender - m_internalCharacterInfo[m_characterCount].baseLine;
4134  lineOffsetDelta = 0 - m_maxLineDescender + ascender + (lineGap + m_lineSpacing + m_lineSpacingDelta) * baseScale;
4135  m_lineOffset += lineOffsetDelta;
4136 
4137  m_startOfLineAscender = ascender;
4138  }
4139  else
4140  m_lineOffset += m_lineHeight + m_lineSpacing * baseScale;
4141 
4142  m_maxLineAscender = k_LargeNegativeFloat;
4143  m_maxLineDescender = k_LargePositiveFloat;
4144 
4145  m_xAdvance = 0 + tag_Indent;
4146 
4147  continue;
4148  }
4149  #endregion End Word Wrapping
4150 
4151  // Text Auto-Sizing (text exceeding Width of container.
4152  #region Handle Text Auto-Sizing
4153  if (ignoreTextAutoSizing == false && defaultFontSize > m_fontSizeMin)
4154  {
4155  // Handle Character Width Adjustments
4156  #region Character Width Adjustments
4157  if (m_charWidthAdjDelta < m_charWidthMaxAdj / 100)
4158  {
4159  m_recursiveCount = 0;
4160  m_charWidthAdjDelta += 0.01f;
4161  return CalculatePreferredValues(defaultFontSize, marginSize, false);
4162  }
4163  #endregion
4164 
4165  // Adjust Point Size
4166  m_maxFontSize = defaultFontSize;
4167 
4168  defaultFontSize -= Mathf.Max((defaultFontSize - m_minFontSize) / 2, 0.05f);
4169  defaultFontSize = (int)(Mathf.Max(defaultFontSize, m_fontSizeMin) * 20 + 0.5f) / 20f;
4170 
4171  if (m_recursiveCount > 20) return new Vector2(renderedWidth, renderedHeight);
4172  return CalculatePreferredValues(defaultFontSize, marginSize, false);
4173  }
4174  #endregion End Text Auto-Sizing
4175  }
4176  #endregion End Check for Characters Exceeding Width of Text Container
4177 
4178  }
4179  #endregion Handle Visible Characters
4180 
4181 
4182  // Check if Line Spacing of previous line needs to be adjusted.
4183  #region Adjust Line Spacing
4184  if (m_lineNumber > 0 && !TMP_Math.Approximately(m_maxLineAscender, m_startOfLineAscender) && m_lineHeight == TMP_Math.FLOAT_UNSET && !m_isNewPage)
4185  {
4186  //Debug.Log("Inline - Adjusting Line Spacing on line #" + m_lineNumber);
4187  //float gap = 0; // Compute gap.
4188 
4189  float offsetDelta = m_maxLineAscender - m_startOfLineAscender;
4190  //AdjustLineOffset(m_firstCharacterOfLine, m_characterCount, offsetDelta);
4191  elementDescenderII -= offsetDelta;
4192  m_lineOffset += offsetDelta;
4193 
4194  m_startOfLineAscender += offsetDelta;
4195  savedWordWrapState.lineOffset = m_lineOffset;
4196  savedWordWrapState.previousLineAscender = m_startOfLineAscender;
4197  }
4198  #endregion
4199 
4200 
4201  // Check if text Exceeds the vertical bounds of the margin area.
4202  #region Check Vertical Bounds & Auto-Sizing
4203  /*
4204  if (m_maxAscender - elementDescenderII > marginHeight + 0.0001f)
4205  {
4206  // Handle Line spacing adjustments
4207  #region Line Spacing Adjustments
4208  if (m_enableAutoSizing && m_lineSpacingDelta > m_lineSpacingMax && m_lineNumber > 0)
4209  {
4210  //loopCountA = 0;
4211 
4212  //m_lineSpacingDelta -= 1;
4213  //GenerateTextMesh();
4214  //return;
4215  }
4216  #endregion
4217 
4218 
4219  // Handle Text Auto-sizing resulting from text exceeding vertical bounds.
4220  #region Text Auto-Sizing (Text greater than vertical bounds)
4221  if (m_enableAutoSizing && m_fontSize > m_fontSizeMin)
4222  {
4223  m_maxFontSize = m_fontSize;
4224 
4225  m_fontSize -= Mathf.Max((m_fontSize - m_minFontSize) / 2, 0.05f);
4226  m_fontSize = (int)(Mathf.Max(m_fontSize, m_fontSizeMin) * 20 + 0.5f) / 20f;
4227 
4228  //m_recursiveCount = 0;
4229  //if (loopCountA > 20) return; // Added to debug
4230  CalculatePreferredValues(m_fontSize, marginSize, false);
4231  return Vector2.zero;
4232  }
4233  #endregion Text Auto-Sizing
4234  }
4235  */
4236  #endregion Check Vertical Bounds
4237 
4238 
4239  // Handle xAdvance & Tabulation Stops. Tab stops at every 25% of Font Size.
4240  #region XAdvance, Tabulation & Stops
4241  if (charCode == 9)
4242  {
4243  float tabSize = m_currentFontAsset.fontInfo.TabWidth * currentElementScale;
4244  float tabs = Mathf.Ceil(m_xAdvance / tabSize) * tabSize;
4245  m_xAdvance = tabs > m_xAdvance ? tabs : m_xAdvance + tabSize;
4246  }
4247  else if (m_monoSpacing != 0)
4248  {
4249  m_xAdvance += (m_monoSpacing - monoAdvance + ((m_characterSpacing + m_currentFontAsset.normalSpacingOffset) * currentElementScale) + m_cSpacing) * (1 - m_charWidthAdjDelta);
4250 
4251  if (char.IsWhiteSpace((char)charCode) || charCode == 0x200B)
4252  m_xAdvance += m_wordSpacing * currentElementScale;
4253  }
4254  else
4255  {
4256  m_xAdvance += ((m_cached_TextElement.xAdvance * bold_xAdvance_multiplier + m_characterSpacing + m_currentFontAsset.normalSpacingOffset + glyphAdjustments.xAdvance) * currentElementScale + m_cSpacing) * (1 - m_charWidthAdjDelta);
4257 
4258  if (char.IsWhiteSpace((char)charCode) || charCode == 0x200B)
4259  m_xAdvance += m_wordSpacing * currentElementScale;
4260  }
4261 
4262 
4263  #endregion Tabulation & Stops
4264 
4265 
4266  // Handle Carriage Return
4267  #region Carriage Return
4268  if (charCode == 13)
4269  {
4270  maxXAdvance = Mathf.Max(maxXAdvance, renderedWidth + m_xAdvance);
4271  renderedWidth = 0;
4272  m_xAdvance = 0 + tag_Indent;
4273  }
4274  #endregion Carriage Return
4275 
4276 
4277  // Handle Line Spacing Adjustments + Word Wrapping & special case for last line.
4278  #region Check for Line Feed and Last Character
4279  if (charCode == 10 || m_characterCount == totalCharacterCount - 1)
4280  {
4281  // Check if Line Spacing of previous line needs to be adjusted.
4282  if (m_lineNumber > 0 && !TMP_Math.Approximately(m_maxLineAscender, m_startOfLineAscender) && m_lineHeight == TMP_Math.FLOAT_UNSET)
4283  {
4284  //Debug.Log("(2) Adjusting Line Spacing on line #" + m_lineNumber);
4285  float offsetDelta = m_maxLineAscender - m_startOfLineAscender;
4286  //AdjustLineOffset(m_firstCharacterOfLine, m_characterCount, offsetDelta);
4287  elementDescenderII -= offsetDelta;
4288  m_lineOffset += offsetDelta;
4289  }
4290 
4291  // Calculate lineAscender & make sure if last character is superscript or subscript that we check that as well.
4292  //float lineAscender = m_maxLineAscender - m_lineOffset;
4293  float lineDescender = m_maxLineDescender - m_lineOffset;
4294 
4295  // Update maxDescender and maxVisibleDescender
4296  m_maxDescender = m_maxDescender < lineDescender ? m_maxDescender : lineDescender;
4297 
4298  m_firstCharacterOfLine = m_characterCount + 1;
4299 
4300  // Store PreferredWidth paying attention to linefeed and last character of text.
4301  if (charCode == 10 && m_characterCount != totalCharacterCount - 1)
4302  {
4303  maxXAdvance = Mathf.Max(maxXAdvance, renderedWidth + linebreakingWidth);
4304  renderedWidth = 0;
4305  }
4306  else
4307  renderedWidth = Mathf.Max(maxXAdvance, renderedWidth + linebreakingWidth);
4308 
4309 
4310  renderedHeight = m_maxAscender - m_maxDescender;
4311 
4312 
4313  // Add new line if not last lines or character.
4314  if (charCode == 10)
4315  {
4316  // Store the state of the line before starting on the new line.
4317  SaveWordWrappingState(ref savedLineState, i, m_characterCount);
4318  // Store the state of the last Character before the new line.
4319  SaveWordWrappingState(ref savedWordWrapState, i, m_characterCount);
4320 
4321  m_lineNumber += 1;
4322 
4323  // Apply Line Spacing
4324  if (m_lineHeight == TMP_Math.FLOAT_UNSET)
4325  {
4326  lineOffsetDelta = 0 - m_maxLineDescender + elementAscender + (lineGap + m_lineSpacing + m_paragraphSpacing + m_lineSpacingDelta) * baseScale;
4327  m_lineOffset += lineOffsetDelta;
4328  }
4329  else
4330  m_lineOffset += m_lineHeight + (m_lineSpacing + m_paragraphSpacing) * baseScale;
4331 
4332  m_maxLineAscender = k_LargeNegativeFloat;
4333  m_maxLineDescender = k_LargePositiveFloat;
4334  m_startOfLineAscender = elementAscender;
4335 
4336  m_xAdvance = 0 + tag_LineIndent + tag_Indent;
4337 
4338  m_characterCount += 1;
4339  continue;
4340  }
4341  }
4342  #endregion Check for Linefeed or Last Character
4343 
4344 
4345  // Save State of Mesh Creation for handling of Word Wrapping
4346  #region Save Word Wrapping State
4347  if (m_enableWordWrapping || m_overflowMode == TextOverflowModes.Truncate || m_overflowMode == TextOverflowModes.Ellipsis)
4348  {
4349  if ((char.IsWhiteSpace((char)charCode) || charCode == 0x200B || charCode == 0x2D || charCode == 0xAD) && !m_isNonBreakingSpace && charCode != 0xA0 && charCode != 0x2011 && charCode != 0x202F && charCode != 0x2060)
4350  {
4351  // We store the state of numerous variables for the most recent Space, LineFeed or Carriage Return to enable them to be restored
4352  // for Word Wrapping.
4353  SaveWordWrappingState(ref savedWordWrapState, i, m_characterCount);
4354  m_isCharacterWrappingEnabled = false;
4355  isFirstWord = false;
4356  }
4357  // Handling for East Asian languages
4358  else if ((charCode > 0x1100 && charCode < 0x11ff || /* Hangul Jamo */
4359  charCode > 0x2E80 && charCode < 0x9FFF || /* CJK */
4360  charCode > 0xA960 && charCode < 0xA97F || /* Hangul Jame Extended-A */
4361  charCode > 0xAC00 && charCode < 0xD7FF || /* Hangul Syllables */
4362  charCode > 0xF900 && charCode < 0xFAFF || /* CJK Compatibility Ideographs */
4363  charCode > 0xFE30 && charCode < 0xFE4F || /* CJK Compatibility Forms */
4364  charCode > 0xFF00 && charCode < 0xFFEF) /* CJK Halfwidth */
4365  && !m_isNonBreakingSpace)
4366  {
4367  if (isFirstWord || isLastBreakingChar || TMP_Settings.linebreakingRules.leadingCharacters.ContainsKey(charCode) == false &&
4368  (m_characterCount < totalCharacterCount - 1 &&
4369  TMP_Settings.linebreakingRules.followingCharacters.ContainsKey(m_internalCharacterInfo[m_characterCount + 1].character) == false))
4370  {
4371  SaveWordWrappingState(ref savedWordWrapState, i, m_characterCount);
4372  m_isCharacterWrappingEnabled = false;
4373  isFirstWord = false;
4374  }
4375  }
4376  else if ((isFirstWord || m_isCharacterWrappingEnabled == true || isLastBreakingChar))
4377  SaveWordWrappingState(ref savedWordWrapState, i, m_characterCount);
4378  }
4379  #endregion Save Word Wrapping State
4380 
4381  m_characterCount += 1;
4382  }
4383 
4384  // Check Auto Sizing and increase font size to fill text container.
4385  #region Check Auto-Sizing (Upper Font Size Bounds)
4386  fontSizeDelta = m_maxFontSize - m_minFontSize;
4387  if (!m_isCharacterWrappingEnabled && ignoreTextAutoSizing == false && fontSizeDelta > 0.051f && defaultFontSize < m_fontSizeMax)
4388  {
4389  m_minFontSize = defaultFontSize;
4390  defaultFontSize += Mathf.Max((m_maxFontSize - defaultFontSize) / 2, 0.05f);
4391  defaultFontSize = (int)(Mathf.Min(defaultFontSize, m_fontSizeMax) * 20 + 0.5f) / 20f;
4392 
4393  if (m_recursiveCount > 20) return new Vector2(renderedWidth, renderedHeight);
4394  return CalculatePreferredValues(defaultFontSize, marginSize, false);
4395  }
4396  #endregion End Auto-sizing Check
4397 
4398 
4399  m_isCharacterWrappingEnabled = false;
4400  m_isCalculatingPreferredValues = false;
4401 
4402  // Adjust Preferred Width and Height to account for Margins.
4403  renderedWidth += m_margin.x > 0 ? m_margin.x : 0;
4404  renderedWidth += m_margin.z > 0 ? m_margin.z : 0;
4405 
4406  renderedHeight += m_margin.y > 0 ? m_margin.y : 0;
4407  renderedHeight += m_margin.w > 0 ? m_margin.w : 0;
4408 
4409  // Round Preferred Values to nearest 5/100.
4410  renderedWidth = (int)(renderedWidth * 100 + 1f) / 100f;
4411  renderedHeight = (int)(renderedHeight * 100 + 1f) / 100f;
4412 
4413  //Debug.Log("Preferred Values: (" + renderedWidth + ", " + renderedHeight + ") with Recursive count of " + m_recursiveCount);
4414 
4416  return new Vector2(renderedWidth, renderedHeight);
4417  }
4418 
4419 
4424  protected virtual Bounds GetCompoundBounds() { return new Bounds(); }
4425 
4426 
4431  protected Bounds GetTextBounds()
4432  {
4433  if (m_textInfo == null || m_textInfo.characterCount > m_textInfo.characterInfo.Length) return new Bounds();
4434 
4435  Extents extent = new Extents(k_LargePositiveVector2, k_LargeNegativeVector2);
4436 
4437  for (int i = 0; i < m_textInfo.characterCount && i < m_textInfo.characterInfo.Length; i++)
4438  {
4439  if (!m_textInfo.characterInfo[i].isVisible) continue;
4440 
4441  extent.min.x = Mathf.Min(extent.min.x, m_textInfo.characterInfo[i].bottomLeft.x);
4442  extent.min.y = Mathf.Min(extent.min.y, m_textInfo.characterInfo[i].descender);
4443 
4444  extent.max.x = Mathf.Max(extent.max.x, m_textInfo.characterInfo[i].xAdvance);
4445  extent.max.y = Mathf.Max(extent.max.y, m_textInfo.characterInfo[i].ascender);
4446  }
4447 
4448  Vector2 size;
4449  size.x = extent.max.x - extent.min.x;
4450  size.y = extent.max.y - extent.min.y;
4451 
4452  Vector3 center = (extent.min + extent.max) / 2;
4453 
4454  return new Bounds(center, size);
4455  }
4456 
4457 
4463  protected Bounds GetTextBounds(bool onlyVisibleCharacters)
4464  {
4465  if (m_textInfo == null) return new Bounds();
4466 
4467  Extents extent = new Extents(k_LargePositiveVector2, k_LargeNegativeVector2);
4468 
4469  for (int i = 0; i < m_textInfo.characterCount; i++)
4470  {
4471  if ((i > maxVisibleCharacters || m_textInfo.characterInfo[i].lineNumber > m_maxVisibleLines) && onlyVisibleCharacters) break;
4472 
4473  if (onlyVisibleCharacters && !m_textInfo.characterInfo[i].isVisible) continue;
4474 
4475  extent.min.x = Mathf.Min(extent.min.x, m_textInfo.characterInfo[i].origin);
4476  extent.min.y = Mathf.Min(extent.min.y, m_textInfo.characterInfo[i].descender);
4477 
4478  extent.max.x = Mathf.Max(extent.max.x, m_textInfo.characterInfo[i].xAdvance);
4479  extent.max.y = Mathf.Max(extent.max.y, m_textInfo.characterInfo[i].ascender);
4480  }
4481 
4482  Vector2 size;
4483  size.x = extent.max.x - extent.min.x;
4484  size.y = extent.max.y - extent.min.y;
4485 
4486  Vector2 center = (extent.min + extent.max) / 2;
4487 
4488  return new Bounds(center, size);
4489  }
4490 
4491 
4498  protected virtual void AdjustLineOffset(int startIndex, int endIndex, float offset) { }
4499 
4500 
4505  protected void ResizeLineExtents(int size)
4506  {
4507  size = size > 1024 ? size + 256 : Mathf.NextPowerOfTwo(size + 1);
4508 
4509  TMP_LineInfo[] temp_lineInfo = new TMP_LineInfo[size];
4510  for (int i = 0; i < size; i++)
4511  {
4512  if (i < m_textInfo.lineInfo.Length)
4513  temp_lineInfo[i] = m_textInfo.lineInfo[i];
4514  else
4515  {
4516  temp_lineInfo[i].lineExtents.min = k_LargePositiveVector2;
4517  temp_lineInfo[i].lineExtents.max = k_LargeNegativeVector2;
4518 
4519  temp_lineInfo[i].ascender = k_LargeNegativeFloat;
4520  temp_lineInfo[i].descender = k_LargePositiveFloat;
4521  }
4522  }
4523 
4524  m_textInfo.lineInfo = temp_lineInfo;
4525  }
4526  protected static Vector2 k_LargePositiveVector2 = new Vector2(TMP_Math.INT_MAX, TMP_Math.INT_MAX);
4527  protected static Vector2 k_LargeNegativeVector2 = new Vector2(TMP_Math.INT_MIN, TMP_Math.INT_MIN);
4528  protected static float k_LargePositiveFloat = TMP_Math.FLOAT_MAX;
4529  protected static float k_LargeNegativeFloat = TMP_Math.FLOAT_MIN;
4530  protected static int k_LargePositiveInt = TMP_Math.INT_MAX;
4531  protected static int k_LargeNegativeInt = TMP_Math.INT_MIN;
4532 
4538  public virtual TMP_TextInfo GetTextInfo(string text) { return null; }
4539 
4540 
4544  public virtual void ComputeMarginSize() { }
4545 
4546 
4552  //protected int GetArraySizes(int[] chars)
4553  //{
4554  // //Debug.Log("Set Array Size called.");
4555 
4556  // //int visibleCount = 0;
4557  // //int totalCount = 0;
4558  // int tagEnd = 0;
4559 
4560  // m_totalCharacterCount = 0;
4561  // m_isUsingBold = false;
4562  // m_isParsingText = false;
4563 
4564 
4565  // //m_VisibleCharacters.Clear();
4566 
4567  // for (int i = 0; chars[i] != 0; i++)
4568  // {
4569  // int c = chars[i];
4570 
4571  // if (m_isRichText && c == 60) // if Char '<'
4572  // {
4573  // // Check if Tag is Valid
4574  // if (ValidateHtmlTag(chars, i + 1, out tagEnd))
4575  // {
4576  // i = tagEnd;
4577  // //if ((m_style & FontStyles.Underline) == FontStyles.Underline) visibleCount += 3;
4578 
4579  // if ((m_style & FontStyles.Bold) == FontStyles.Bold) m_isUsingBold = true;
4580 
4581  // continue;
4582  // }
4583  // }
4584 
4585  // //if (!char.IsWhiteSpace((char)c) && c != 0x200B)
4586  // //{
4587  // //visibleCount += 1;
4588  // //}
4589 
4590  // //m_VisibleCharacters.Add((char)c);
4591  // m_totalCharacterCount += 1;
4592  // }
4593 
4594  // return m_totalCharacterCount;
4595  //}
4596 
4597 
4604  protected void SaveWordWrappingState(ref WordWrapState state, int index, int count)
4605  {
4606  // Multi Font & Material support related
4607  state.currentFontAsset = m_currentFontAsset;
4608  state.currentSpriteAsset = m_currentSpriteAsset;
4609  state.currentMaterial = m_currentMaterial;
4610  state.currentMaterialIndex = m_currentMaterialIndex;
4611 
4612  state.previous_WordBreak = index;
4613  state.total_CharacterCount = count;
4614  state.visible_CharacterCount = m_lineVisibleCharacterCount;
4615  //state.visible_CharacterCount = m_visibleCharacterCount;
4616  //state.visible_SpriteCount = m_visibleSpriteCount;
4617  state.visible_LinkCount = m_textInfo.linkCount;
4618 
4619  state.firstCharacterIndex = m_firstCharacterOfLine;
4620  state.firstVisibleCharacterIndex = m_firstVisibleCharacterOfLine;
4621  state.lastVisibleCharIndex = m_lastVisibleCharacterOfLine;
4622 
4623  state.fontStyle = m_style;
4624  state.fontScale = m_fontScale;
4625  //state.maxFontScale = m_maxFontScale;
4626  state.fontScaleMultiplier = m_fontScaleMultiplier;
4627  state.currentFontSize = m_currentFontSize;
4628 
4629  state.xAdvance = m_xAdvance;
4630  state.maxCapHeight = m_maxCapHeight;
4631  state.maxAscender = m_maxAscender;
4632  state.maxDescender = m_maxDescender;
4633  state.maxLineAscender = m_maxLineAscender;
4634  state.maxLineDescender = m_maxLineDescender;
4635  state.previousLineAscender = m_startOfLineAscender;
4636  state.preferredWidth = m_preferredWidth;
4637  state.preferredHeight = m_preferredHeight;
4638  state.meshExtents = m_meshExtents;
4639 
4640  state.lineNumber = m_lineNumber;
4641  state.lineOffset = m_lineOffset;
4642  state.baselineOffset = m_baselineOffset;
4643 
4644  //state.alignment = m_lineJustification;
4645  state.vertexColor = m_htmlColor;
4646  state.underlineColor = m_underlineColor;
4647  state.strikethroughColor = m_strikethroughColor;
4648  state.highlightColor = m_highlightColor;
4649 
4650  state.isNonBreakingSpace = m_isNonBreakingSpace;
4651  state.tagNoParsing = tag_NoParsing;
4652 
4653  // XML Tag Stack
4654  state.basicStyleStack = m_fontStyleStack;
4655  state.colorStack = m_colorStack;
4656  state.underlineColorStack = m_underlineColorStack;
4657  state.strikethroughColorStack = m_strikethroughColorStack;
4658  state.highlightColorStack = m_highlightColorStack;
4659  state.colorGradientStack = m_colorGradientStack;
4660  state.sizeStack = m_sizeStack;
4661  state.indentStack = m_indentStack;
4662  state.fontWeightStack = m_fontWeightStack;
4663  state.styleStack = m_styleStack;
4664  state.baselineStack = m_baselineOffsetStack;
4665  state.actionStack = m_actionStack;
4666  state.materialReferenceStack = m_materialReferenceStack;
4667  state.lineJustificationStack = m_lineJustificationStack;
4668  //state.spriteAnimationStack = m_spriteAnimationStack;
4669 
4670  state.spriteAnimationID = m_spriteAnimationID;
4671 
4672  if (m_lineNumber < m_textInfo.lineInfo.Length)
4673  state.lineInfo = m_textInfo.lineInfo[m_lineNumber];
4674  }
4675 
4676 
4682  protected int RestoreWordWrappingState(ref WordWrapState state)
4683  {
4684  int index = state.previous_WordBreak;
4685 
4686  // Multi Font & Material support related
4687  m_currentFontAsset = state.currentFontAsset;
4688  m_currentSpriteAsset = state.currentSpriteAsset;
4689  m_currentMaterial = state.currentMaterial;
4690  m_currentMaterialIndex = state.currentMaterialIndex;
4691 
4692  m_characterCount = state.total_CharacterCount + 1;
4693  m_lineVisibleCharacterCount = state.visible_CharacterCount;
4694  //m_visibleCharacterCount = state.visible_CharacterCount;
4695  //m_visibleSpriteCount = state.visible_SpriteCount;
4696  m_textInfo.linkCount = state.visible_LinkCount;
4697 
4698  m_firstCharacterOfLine = state.firstCharacterIndex;
4699  m_firstVisibleCharacterOfLine = state.firstVisibleCharacterIndex;
4700  m_lastVisibleCharacterOfLine = state.lastVisibleCharIndex;
4701 
4702  m_style = state.fontStyle;
4703  m_fontScale = state.fontScale;
4704  m_fontScaleMultiplier = state.fontScaleMultiplier;
4705  //m_maxFontScale = state.maxFontScale;
4706  m_currentFontSize = state.currentFontSize;
4707 
4708  m_xAdvance = state.xAdvance;
4709  m_maxCapHeight = state.maxCapHeight;
4710  m_maxAscender = state.maxAscender;
4711  m_maxDescender = state.maxDescender;
4712  m_maxLineAscender = state.maxLineAscender;
4713  m_maxLineDescender = state.maxLineDescender;
4714  m_startOfLineAscender = state.previousLineAscender;
4715  m_preferredWidth = state.preferredWidth;
4716  m_preferredHeight = state.preferredHeight;
4717  m_meshExtents = state.meshExtents;
4718 
4719  m_lineNumber = state.lineNumber;
4720  m_lineOffset = state.lineOffset;
4721  m_baselineOffset = state.baselineOffset;
4722 
4723  //m_lineJustification = state.alignment;
4724  m_htmlColor = state.vertexColor;
4725  m_underlineColor = state.underlineColor;
4726  m_strikethroughColor = state.strikethroughColor;
4727  m_highlightColor = state.highlightColor;
4728 
4729  m_isNonBreakingSpace = state.isNonBreakingSpace;
4730  tag_NoParsing = state.tagNoParsing;
4731 
4732  // XML Tag Stack
4733  m_fontStyleStack = state.basicStyleStack;
4734  m_colorStack = state.colorStack;
4735  m_underlineColorStack = state.underlineColorStack;
4736  m_strikethroughColorStack = state.strikethroughColorStack;
4737  m_highlightColorStack = state.highlightColorStack;
4738  m_colorGradientStack = state.colorGradientStack;
4739  m_sizeStack = state.sizeStack;
4740  m_indentStack = state.indentStack;
4741  m_fontWeightStack = state.fontWeightStack;
4742  m_styleStack = state.styleStack;
4743  m_baselineOffsetStack = state.baselineStack;
4744  m_actionStack = state.actionStack;
4745  m_materialReferenceStack = state.materialReferenceStack;
4746  m_lineJustificationStack = state.lineJustificationStack;
4747  //m_spriteAnimationStack = state.spriteAnimationStack;
4748 
4749  m_spriteAnimationID = state.spriteAnimationID;
4750 
4751  if (m_lineNumber < m_textInfo.lineInfo.Length)
4752  m_textInfo.lineInfo[m_lineNumber] = state.lineInfo;
4753 
4754  return index;
4755  }
4756 
4757 
4763  protected virtual void SaveGlyphVertexInfo(float padding, float style_padding, Color32 vertexColor)
4764  {
4765  // Save the Vertex Position for the Character
4766  #region Setup Mesh Vertices
4767  m_textInfo.characterInfo[m_characterCount].vertex_BL.position = m_textInfo.characterInfo[m_characterCount].bottomLeft;
4768  m_textInfo.characterInfo[m_characterCount].vertex_TL.position = m_textInfo.characterInfo[m_characterCount].topLeft;
4769  m_textInfo.characterInfo[m_characterCount].vertex_TR.position = m_textInfo.characterInfo[m_characterCount].topRight;
4770  m_textInfo.characterInfo[m_characterCount].vertex_BR.position = m_textInfo.characterInfo[m_characterCount].bottomRight;
4771  #endregion
4772 
4773 
4774  #region Setup Vertex Colors
4775  // Alpha is the lower of the vertex color or tag color alpha used.
4776  vertexColor.a = m_fontColor32.a < vertexColor.a ? (byte)(m_fontColor32.a) : (byte)(vertexColor.a);
4777 
4778  // Handle Vertex Colors & Vertex Color Gradient
4779  if (!m_enableVertexGradient)
4780  {
4781  m_textInfo.characterInfo[m_characterCount].vertex_BL.color = vertexColor;
4782  m_textInfo.characterInfo[m_characterCount].vertex_TL.color = vertexColor;
4783  m_textInfo.characterInfo[m_characterCount].vertex_TR.color = vertexColor;
4784  m_textInfo.characterInfo[m_characterCount].vertex_BR.color = vertexColor;
4785  }
4786  else
4787  {
4788  if (!m_overrideHtmlColors && m_colorStack.index > 1)
4789  {
4790  m_textInfo.characterInfo[m_characterCount].vertex_BL.color = vertexColor;
4791  m_textInfo.characterInfo[m_characterCount].vertex_TL.color = vertexColor;
4792  m_textInfo.characterInfo[m_characterCount].vertex_TR.color = vertexColor;
4793  m_textInfo.characterInfo[m_characterCount].vertex_BR.color = vertexColor;
4794  }
4795  else // Handle Vertex Color Gradient
4796  {
4797  // Use Vertex Color Gradient Preset (if one is assigned)
4798  if (m_fontColorGradientPreset != null)
4799  {
4800  m_textInfo.characterInfo[m_characterCount].vertex_BL.color = m_fontColorGradientPreset.bottomLeft * vertexColor;
4801  m_textInfo.characterInfo[m_characterCount].vertex_TL.color = m_fontColorGradientPreset.topLeft * vertexColor;
4802  m_textInfo.characterInfo[m_characterCount].vertex_TR.color = m_fontColorGradientPreset.topRight * vertexColor;
4803  m_textInfo.characterInfo[m_characterCount].vertex_BR.color = m_fontColorGradientPreset.bottomRight * vertexColor;
4804  }
4805  else
4806  {
4807  m_textInfo.characterInfo[m_characterCount].vertex_BL.color = m_fontColorGradient.bottomLeft * vertexColor;
4808  m_textInfo.characterInfo[m_characterCount].vertex_TL.color = m_fontColorGradient.topLeft * vertexColor;
4809  m_textInfo.characterInfo[m_characterCount].vertex_TR.color = m_fontColorGradient.topRight * vertexColor;
4810  m_textInfo.characterInfo[m_characterCount].vertex_BR.color = m_fontColorGradient.bottomRight * vertexColor;
4811  }
4812  }
4813  }
4814 
4815  if (m_colorGradientPreset != null)
4816  {
4817  m_textInfo.characterInfo[m_characterCount].vertex_BL.color *= m_colorGradientPreset.bottomLeft;
4818  m_textInfo.characterInfo[m_characterCount].vertex_TL.color *= m_colorGradientPreset.topLeft;
4819  m_textInfo.characterInfo[m_characterCount].vertex_TR.color *= m_colorGradientPreset.topRight;
4820  m_textInfo.characterInfo[m_characterCount].vertex_BR.color *= m_colorGradientPreset.bottomRight;
4821  }
4822  #endregion
4823 
4824  // Apply style_padding only if this is a SDF Shader.
4825  if (!m_isSDFShader)
4826  style_padding = 0;
4827 
4828 
4829  // Setup UVs for the Character
4830  #region Setup UVs
4831  FaceInfo faceInfo = m_currentFontAsset.fontInfo;
4832 
4833  Vector2 uv0;
4834  uv0.x = (m_cached_TextElement.x - padding - style_padding) / faceInfo.AtlasWidth;
4835  uv0.y = 1 - (m_cached_TextElement.y + padding + style_padding + m_cached_TextElement.height) / faceInfo.AtlasHeight;
4836 
4837  Vector2 uv1;
4838  uv1.x = uv0.x;
4839  uv1.y = 1 - (m_cached_TextElement.y - padding - style_padding) / faceInfo.AtlasHeight;
4840 
4841  Vector2 uv2;
4842  uv2.x = (m_cached_TextElement.x + padding + style_padding + m_cached_TextElement.width) / faceInfo.AtlasWidth;
4843  uv2.y = uv1.y;
4844 
4845  Vector2 uv3;
4846  uv3.x = uv2.x;
4847  uv3.y = uv0.y;
4848 
4849  //Vector2 uv0 = new Vector2((m_cached_TextElement.x - padding - style_padding) / faceInfo.AtlasWidth, 1 - (m_cached_TextElement.y + padding + style_padding + m_cached_TextElement.height) / faceInfo.AtlasHeight); // bottom left
4850  //Vector2 uv1 = new Vector2(uv0.x, 1 - (m_cached_TextElement.y - padding - style_padding) / faceInfo.AtlasHeight); // top left
4851  //Vector2 uv2 = new Vector2((m_cached_TextElement.x + padding + style_padding + m_cached_TextElement.width) / faceInfo.AtlasWidth, uv1.y); // top right
4852  //Vector2 uv3 = new Vector2(uv2.x, uv0.y); // bottom right
4853 
4854  // Store UV Information
4855  m_textInfo.characterInfo[m_characterCount].vertex_BL.uv = uv0;
4856  m_textInfo.characterInfo[m_characterCount].vertex_TL.uv = uv1;
4857  m_textInfo.characterInfo[m_characterCount].vertex_TR.uv = uv2;
4858  m_textInfo.characterInfo[m_characterCount].vertex_BR.uv = uv3;
4859  #endregion Setup UVs
4860 
4861 
4862  // Normal
4863  #region Setup Normals & Tangents
4864  //Vector3 normal = new Vector3(0, 0, -1);
4865  //m_textInfo.characterInfo[m_characterCount].vertex_BL.normal = normal;
4866  //m_textInfo.characterInfo[m_characterCount].vertex_TL.normal = normal;
4867  //m_textInfo.characterInfo[m_characterCount].vertex_TR.normal = normal;
4868  //m_textInfo.characterInfo[m_characterCount].vertex_BR.normal = normal;
4869 
4870  // Tangents
4871  //Vector4 tangent = new Vector4(-1, 0, 0, 1);
4872  //m_textInfo.characterInfo[m_characterCount].vertex_BL.tangent = tangent;
4873  //m_textInfo.characterInfo[m_characterCount].vertex_TL.tangent = tangent;
4874  //m_textInfo.characterInfo[m_characterCount].vertex_TR.tangent = tangent;
4875  //m_textInfo.characterInfo[m_characterCount].vertex_BR.tangent = tangent;
4876  #endregion end Normals & Tangents
4877  }
4878 
4879 
4886  protected virtual void SaveSpriteVertexInfo(Color32 vertexColor)
4887  {
4888  // Save the Vertex Position for the Character
4889  #region Setup Mesh Vertices
4890  m_textInfo.characterInfo[m_characterCount].vertex_BL.position = m_textInfo.characterInfo[m_characterCount].bottomLeft;
4891  m_textInfo.characterInfo[m_characterCount].vertex_TL.position = m_textInfo.characterInfo[m_characterCount].topLeft;
4892  m_textInfo.characterInfo[m_characterCount].vertex_TR.position = m_textInfo.characterInfo[m_characterCount].topRight;
4893  m_textInfo.characterInfo[m_characterCount].vertex_BR.position = m_textInfo.characterInfo[m_characterCount].bottomRight;
4894  #endregion
4895 
4896  // Vertex Color Alpha
4897  if (m_tintAllSprites) m_tintSprite = true;
4898  Color32 spriteColor = m_tintSprite ? m_spriteColor.Multiply(vertexColor) : m_spriteColor;
4899  spriteColor.a = spriteColor.a < m_fontColor32.a ? spriteColor.a = spriteColor.a < vertexColor.a ? spriteColor.a : vertexColor.a : m_fontColor32.a;
4900 
4901  Color32 c0 = spriteColor;
4902  Color32 c1 = spriteColor;
4903  Color32 c2 = spriteColor;
4904  Color32 c3 = spriteColor;
4905 
4906  if (m_enableVertexGradient)
4907  {
4908  if (m_fontColorGradientPreset != null)
4909  {
4910  c0 = m_tintSprite ? c0.Multiply(m_fontColorGradientPreset.bottomLeft) : c0;
4911  c1 = m_tintSprite ? c1.Multiply(m_fontColorGradientPreset.topLeft) : c1;
4912  c2 = m_tintSprite ? c2.Multiply(m_fontColorGradientPreset.topRight) : c2;
4913  c3 = m_tintSprite ? c3.Multiply(m_fontColorGradientPreset.bottomRight) : c3;
4914  }
4915  else
4916  {
4917  c0 = m_tintSprite ? c0.Multiply(m_fontColorGradient.bottomLeft) : c0;
4918  c1 = m_tintSprite ? c1.Multiply(m_fontColorGradient.topLeft) : c1;
4919  c2 = m_tintSprite ? c2.Multiply(m_fontColorGradient.topRight) : c2;
4920  c3 = m_tintSprite ? c3.Multiply(m_fontColorGradient.bottomRight) : c3;
4921  }
4922  }
4923 
4924  if (m_colorGradientPreset != null)
4925  {
4926  c0 = m_tintSprite ? c0.Multiply(m_colorGradientPreset.bottomLeft) : c0;
4927  c1 = m_tintSprite ? c1.Multiply(m_colorGradientPreset.topLeft) : c1;
4928  c2 = m_tintSprite ? c2.Multiply(m_colorGradientPreset.topRight) : c2;
4929  c3 = m_tintSprite ? c3.Multiply(m_colorGradientPreset.bottomRight) : c3;
4930  }
4931 
4932  m_textInfo.characterInfo[m_characterCount].vertex_BL.color = c0;
4933  m_textInfo.characterInfo[m_characterCount].vertex_TL.color = c1;
4934  m_textInfo.characterInfo[m_characterCount].vertex_TR.color = c2;
4935  m_textInfo.characterInfo[m_characterCount].vertex_BR.color = c3;
4936 
4937 
4938  // Setup UVs for the Character
4939  #region Setup UVs
4940  Vector2 uv0 = new Vector2(m_cached_TextElement.x / m_currentSpriteAsset.spriteSheet.width, m_cached_TextElement.y / m_currentSpriteAsset.spriteSheet.height); // bottom left
4941  Vector2 uv1 = new Vector2(uv0.x, (m_cached_TextElement.y + m_cached_TextElement.height) / m_currentSpriteAsset.spriteSheet.height); // top left
4942  Vector2 uv2 = new Vector2((m_cached_TextElement.x + m_cached_TextElement.width) / m_currentSpriteAsset.spriteSheet.width, uv1.y); // top right
4943  Vector2 uv3 = new Vector2(uv2.x, uv0.y); // bottom right
4944 
4945  // Store UV Information
4946  m_textInfo.characterInfo[m_characterCount].vertex_BL.uv = uv0;
4947  m_textInfo.characterInfo[m_characterCount].vertex_TL.uv = uv1;
4948  m_textInfo.characterInfo[m_characterCount].vertex_TR.uv = uv2;
4949  m_textInfo.characterInfo[m_characterCount].vertex_BR.uv = uv3;
4950  #endregion Setup UVs
4951 
4952 
4953  // Normal
4954  #region Setup Normals & Tangents
4955  //Vector3 normal = new Vector3(0, 0, -1);
4956  //m_textInfo.characterInfo[m_characterCount].vertex_BL.normal = normal;
4957  //m_textInfo.characterInfo[m_characterCount].vertex_TL.normal = normal;
4958  //m_textInfo.characterInfo[m_characterCount].vertex_TR.normal = normal;
4959  //m_textInfo.characterInfo[m_characterCount].vertex_BR.normal = normal;
4960 
4961  // Tangents
4962  //Vector4 tangent = new Vector4(-1, 0, 0, 1);
4963  //m_textInfo.characterInfo[m_characterCount].vertex_BL.tangent = tangent;
4964  //m_textInfo.characterInfo[m_characterCount].vertex_TL.tangent = tangent;
4965  //m_textInfo.characterInfo[m_characterCount].vertex_TR.tangent = tangent;
4966  //m_textInfo.characterInfo[m_characterCount].vertex_BR.tangent = tangent;
4967  #endregion end Normals & Tangents
4968 
4969  }
4970 
4971 
4977  protected virtual void FillCharacterVertexBuffers(int i, int index_X4)
4978  {
4979  int materialIndex = m_textInfo.characterInfo[i].materialReferenceIndex;
4980  index_X4 = m_textInfo.meshInfo[materialIndex].vertexCount;
4981 
4982  // Make sure buffers allocation are sufficient to hold the vertex data
4983  //if (m_textInfo.meshInfo[materialIndex].vertices.Length < index_X4 + 4)
4984  // m_textInfo.meshInfo[materialIndex].ResizeMeshInfo(Mathf.NextPowerOfTwo(index_X4 + 4));
4985 
4986 
4987  TMP_CharacterInfo[] characterInfoArray = m_textInfo.characterInfo;
4988  m_textInfo.characterInfo[i].vertexIndex = index_X4;
4989 
4990  // Setup Vertices for Characters
4991  m_textInfo.meshInfo[materialIndex].vertices[0 + index_X4] = characterInfoArray[i].vertex_BL.position;
4992  m_textInfo.meshInfo[materialIndex].vertices[1 + index_X4] = characterInfoArray[i].vertex_TL.position;
4993  m_textInfo.meshInfo[materialIndex].vertices[2 + index_X4] = characterInfoArray[i].vertex_TR.position;
4994  m_textInfo.meshInfo[materialIndex].vertices[3 + index_X4] = characterInfoArray[i].vertex_BR.position;
4995 
4996 
4997  // Setup UVS0
4998  m_textInfo.meshInfo[materialIndex].uvs0[0 + index_X4] = characterInfoArray[i].vertex_BL.uv;
4999  m_textInfo.meshInfo[materialIndex].uvs0[1 + index_X4] = characterInfoArray[i].vertex_TL.uv;
5000  m_textInfo.meshInfo[materialIndex].uvs0[2 + index_X4] = characterInfoArray[i].vertex_TR.uv;
5001  m_textInfo.meshInfo[materialIndex].uvs0[3 + index_X4] = characterInfoArray[i].vertex_BR.uv;
5002 
5003 
5004  // Setup UVS2
5005  m_textInfo.meshInfo[materialIndex].uvs2[0 + index_X4] = characterInfoArray[i].vertex_BL.uv2;
5006  m_textInfo.meshInfo[materialIndex].uvs2[1 + index_X4] = characterInfoArray[i].vertex_TL.uv2;
5007  m_textInfo.meshInfo[materialIndex].uvs2[2 + index_X4] = characterInfoArray[i].vertex_TR.uv2;
5008  m_textInfo.meshInfo[materialIndex].uvs2[3 + index_X4] = characterInfoArray[i].vertex_BR.uv2;
5009 
5010 
5011  // Setup UVS4
5012  //m_textInfo.meshInfo[0].uvs4[0 + index_X4] = characterInfoArray[i].vertex_BL.uv4;
5013  //m_textInfo.meshInfo[0].uvs4[1 + index_X4] = characterInfoArray[i].vertex_TL.uv4;
5014  //m_textInfo.meshInfo[0].uvs4[2 + index_X4] = characterInfoArray[i].vertex_TR.uv4;
5015  //m_textInfo.meshInfo[0].uvs4[3 + index_X4] = characterInfoArray[i].vertex_BR.uv4;
5016 
5017 
5018  // setup Vertex Colors
5019  m_textInfo.meshInfo[materialIndex].colors32[0 + index_X4] = characterInfoArray[i].vertex_BL.color;
5020  m_textInfo.meshInfo[materialIndex].colors32[1 + index_X4] = characterInfoArray[i].vertex_TL.color;
5021  m_textInfo.meshInfo[materialIndex].colors32[2 + index_X4] = characterInfoArray[i].vertex_TR.color;
5022  m_textInfo.meshInfo[materialIndex].colors32[3 + index_X4] = characterInfoArray[i].vertex_BR.color;
5023 
5024  m_textInfo.meshInfo[materialIndex].vertexCount = index_X4 + 4;
5025  }
5026 
5027 
5028  protected virtual void FillCharacterVertexBuffers(int i, int index_X4, bool isVolumetric)
5029  {
5030  int materialIndex = m_textInfo.characterInfo[i].materialReferenceIndex;
5031  index_X4 = m_textInfo.meshInfo[materialIndex].vertexCount;
5032 
5033  TMP_CharacterInfo[] characterInfoArray = m_textInfo.characterInfo;
5034  m_textInfo.characterInfo[i].vertexIndex = index_X4;
5035 
5036  // Setup Vertices for Characters
5037  m_textInfo.meshInfo[materialIndex].vertices[0 + index_X4] = characterInfoArray[i].vertex_BL.position;
5038  m_textInfo.meshInfo[materialIndex].vertices[1 + index_X4] = characterInfoArray[i].vertex_TL.position;
5039  m_textInfo.meshInfo[materialIndex].vertices[2 + index_X4] = characterInfoArray[i].vertex_TR.position;
5040  m_textInfo.meshInfo[materialIndex].vertices[3 + index_X4] = characterInfoArray[i].vertex_BR.position;
5041 
5042  if (isVolumetric)
5043  {
5044  Vector3 depth = new Vector3(0, 0, m_fontSize * m_fontScale);
5045  m_textInfo.meshInfo[materialIndex].vertices[4 + index_X4] = characterInfoArray[i].vertex_BL.position + depth;
5046  m_textInfo.meshInfo[materialIndex].vertices[5 + index_X4] = characterInfoArray[i].vertex_TL.position + depth;
5047  m_textInfo.meshInfo[materialIndex].vertices[6 + index_X4] = characterInfoArray[i].vertex_TR.position + depth;
5048  m_textInfo.meshInfo[materialIndex].vertices[7 + index_X4] = characterInfoArray[i].vertex_BR.position + depth;
5049  }
5050 
5051  // Setup UVS0
5052  m_textInfo.meshInfo[materialIndex].uvs0[0 + index_X4] = characterInfoArray[i].vertex_BL.uv;
5053  m_textInfo.meshInfo[materialIndex].uvs0[1 + index_X4] = characterInfoArray[i].vertex_TL.uv;
5054  m_textInfo.meshInfo[materialIndex].uvs0[2 + index_X4] = characterInfoArray[i].vertex_TR.uv;
5055  m_textInfo.meshInfo[materialIndex].uvs0[3 + index_X4] = characterInfoArray[i].vertex_BR.uv;
5056 
5057  if (isVolumetric)
5058  {
5059  m_textInfo.meshInfo[materialIndex].uvs0[4 + index_X4] = characterInfoArray[i].vertex_BL.uv;
5060  m_textInfo.meshInfo[materialIndex].uvs0[5 + index_X4] = characterInfoArray[i].vertex_TL.uv;
5061  m_textInfo.meshInfo[materialIndex].uvs0[6 + index_X4] = characterInfoArray[i].vertex_TR.uv;
5062  m_textInfo.meshInfo[materialIndex].uvs0[7 + index_X4] = characterInfoArray[i].vertex_BR.uv;
5063  }
5064 
5065 
5066  // Setup UVS2
5067  m_textInfo.meshInfo[materialIndex].uvs2[0 + index_X4] = characterInfoArray[i].vertex_BL.uv2;
5068  m_textInfo.meshInfo[materialIndex].uvs2[1 + index_X4] = characterInfoArray[i].vertex_TL.uv2;
5069  m_textInfo.meshInfo[materialIndex].uvs2[2 + index_X4] = characterInfoArray[i].vertex_TR.uv2;
5070  m_textInfo.meshInfo[materialIndex].uvs2[3 + index_X4] = characterInfoArray[i].vertex_BR.uv2;
5071 
5072  if (isVolumetric)
5073  {
5074  m_textInfo.meshInfo[materialIndex].uvs2[4 + index_X4] = characterInfoArray[i].vertex_BL.uv2;
5075  m_textInfo.meshInfo[materialIndex].uvs2[5 + index_X4] = characterInfoArray[i].vertex_TL.uv2;
5076  m_textInfo.meshInfo[materialIndex].uvs2[6 + index_X4] = characterInfoArray[i].vertex_TR.uv2;
5077  m_textInfo.meshInfo[materialIndex].uvs2[7 + index_X4] = characterInfoArray[i].vertex_BR.uv2;
5078  }
5079 
5080 
5081  // Setup UVS4
5082  //m_textInfo.meshInfo[0].uvs4[0 + index_X4] = characterInfoArray[i].vertex_BL.uv4;
5083  //m_textInfo.meshInfo[0].uvs4[1 + index_X4] = characterInfoArray[i].vertex_TL.uv4;
5084  //m_textInfo.meshInfo[0].uvs4[2 + index_X4] = characterInfoArray[i].vertex_TR.uv4;
5085  //m_textInfo.meshInfo[0].uvs4[3 + index_X4] = characterInfoArray[i].vertex_BR.uv4;
5086 
5087 
5088  // setup Vertex Colors
5089  m_textInfo.meshInfo[materialIndex].colors32[0 + index_X4] = characterInfoArray[i].vertex_BL.color;
5090  m_textInfo.meshInfo[materialIndex].colors32[1 + index_X4] = characterInfoArray[i].vertex_TL.color;
5091  m_textInfo.meshInfo[materialIndex].colors32[2 + index_X4] = characterInfoArray[i].vertex_TR.color;
5092  m_textInfo.meshInfo[materialIndex].colors32[3 + index_X4] = characterInfoArray[i].vertex_BR.color;
5093 
5094  if (isVolumetric)
5095  {
5096  Color32 backColor = new Color32(255, 255, 128, 255);
5097  m_textInfo.meshInfo[materialIndex].colors32[4 + index_X4] = backColor; //characterInfoArray[i].vertex_BL.color;
5098  m_textInfo.meshInfo[materialIndex].colors32[5 + index_X4] = backColor; //characterInfoArray[i].vertex_TL.color;
5099  m_textInfo.meshInfo[materialIndex].colors32[6 + index_X4] = backColor; //characterInfoArray[i].vertex_TR.color;
5100  m_textInfo.meshInfo[materialIndex].colors32[7 + index_X4] = backColor; //characterInfoArray[i].vertex_BR.color;
5101  }
5102 
5103  m_textInfo.meshInfo[materialIndex].vertexCount = index_X4 + (!isVolumetric ? 4 : 8);
5104  }
5105 
5106 
5112  protected virtual void FillSpriteVertexBuffers(int i, int index_X4)
5113  {
5114  int materialIndex = m_textInfo.characterInfo[i].materialReferenceIndex;
5115  index_X4 = m_textInfo.meshInfo[materialIndex].vertexCount;
5116 
5117  TMP_CharacterInfo[] characterInfoArray = m_textInfo.characterInfo;
5118  m_textInfo.characterInfo[i].vertexIndex = index_X4;
5119 
5120  // Setup Vertices for Characters
5121  m_textInfo.meshInfo[materialIndex].vertices[0 + index_X4] = characterInfoArray[i].vertex_BL.position;
5122  m_textInfo.meshInfo[materialIndex].vertices[1 + index_X4] = characterInfoArray[i].vertex_TL.position;
5123  m_textInfo.meshInfo[materialIndex].vertices[2 + index_X4] = characterInfoArray[i].vertex_TR.position;
5124  m_textInfo.meshInfo[materialIndex].vertices[3 + index_X4] = characterInfoArray[i].vertex_BR.position;
5125 
5126 
5127  // Setup UVS0
5128  m_textInfo.meshInfo[materialIndex].uvs0[0 + index_X4] = characterInfoArray[i].vertex_BL.uv;
5129  m_textInfo.meshInfo[materialIndex].uvs0[1 + index_X4] = characterInfoArray[i].vertex_TL.uv;
5130  m_textInfo.meshInfo[materialIndex].uvs0[2 + index_X4] = characterInfoArray[i].vertex_TR.uv;
5131  m_textInfo.meshInfo[materialIndex].uvs0[3 + index_X4] = characterInfoArray[i].vertex_BR.uv;
5132 
5133 
5134  // Setup UVS2
5135  m_textInfo.meshInfo[materialIndex].uvs2[0 + index_X4] = characterInfoArray[i].vertex_BL.uv2;
5136  m_textInfo.meshInfo[materialIndex].uvs2[1 + index_X4] = characterInfoArray[i].vertex_TL.uv2;
5137  m_textInfo.meshInfo[materialIndex].uvs2[2 + index_X4] = characterInfoArray[i].vertex_TR.uv2;
5138  m_textInfo.meshInfo[materialIndex].uvs2[3 + index_X4] = characterInfoArray[i].vertex_BR.uv2;
5139 
5140 
5141  // Setup UVS4
5142  //m_textInfo.meshInfo[0].uvs4[0 + index_X4] = characterInfoArray[i].vertex_BL.uv4;
5143  //m_textInfo.meshInfo[0].uvs4[1 + index_X4] = characterInfoArray[i].vertex_TL.uv4;
5144  //m_textInfo.meshInfo[0].uvs4[2 + index_X4] = characterInfoArray[i].vertex_TR.uv4;
5145  //m_textInfo.meshInfo[0].uvs4[3 + index_X4] = characterInfoArray[i].vertex_BR.uv4;
5146 
5147 
5148  // setup Vertex Colors
5149  m_textInfo.meshInfo[materialIndex].colors32[0 + index_X4] = characterInfoArray[i].vertex_BL.color;
5150  m_textInfo.meshInfo[materialIndex].colors32[1 + index_X4] = characterInfoArray[i].vertex_TL.color;
5151  m_textInfo.meshInfo[materialIndex].colors32[2 + index_X4] = characterInfoArray[i].vertex_TR.color;
5152  m_textInfo.meshInfo[materialIndex].colors32[3 + index_X4] = characterInfoArray[i].vertex_BR.color;
5153 
5154  m_textInfo.meshInfo[materialIndex].vertexCount = index_X4 + 4;
5155  }
5156 
5157 
5167  protected virtual void DrawUnderlineMesh(Vector3 start, Vector3 end, ref int index, float startScale, float endScale, float maxScale, float sdfScale, Color32 underlineColor)
5168  {
5169  if (m_cached_Underline_GlyphInfo == null)
5170  {
5171  if (!TMP_Settings.warningsDisabled) Debug.LogWarning("Unable to add underline since the Font Asset doesn't contain the underline character.", this);
5172  return;
5173  }
5174 
5175  int verticesCount = index + 12;
5176  // Check to make sure our current mesh buffer allocations can hold these new Quads.
5177  if (verticesCount > m_textInfo.meshInfo[0].vertices.Length)
5178  {
5179  // Resize Mesh Buffers
5180  m_textInfo.meshInfo[0].ResizeMeshInfo(verticesCount / 4);
5181  }
5182 
5183  // Adjust the position of the underline based on the lowest character. This matters for subscript character.
5184  start.y = Mathf.Min(start.y, end.y);
5185  end.y = Mathf.Min(start.y, end.y);
5186 
5187  float segmentWidth = m_cached_Underline_GlyphInfo.width / 2 * maxScale;
5188 
5189  if (end.x - start.x < m_cached_Underline_GlyphInfo.width * maxScale)
5190  {
5191  segmentWidth = (end.x - start.x) / 2f;
5192  }
5193 
5194  float startPadding = m_padding * startScale / maxScale;
5195  float endPadding = m_padding * endScale / maxScale;
5196 
5197  float underlineThickness = m_cached_Underline_GlyphInfo.height;
5198 
5199  // UNDERLINE VERTICES FOR (3) LINE SEGMENTS
5200  #region UNDERLINE VERTICES
5201  Vector3[] vertices = m_textInfo.meshInfo[0].vertices;
5202 
5203  // Front Part of the Underline
5204  vertices[index + 0] = start + new Vector3(0, 0 - (underlineThickness + m_padding) * maxScale, 0); // BL
5205  vertices[index + 1] = start + new Vector3(0, m_padding * maxScale, 0); // TL
5206  vertices[index + 2] = vertices[index + 1] + new Vector3(segmentWidth, 0, 0); // TR
5207  vertices[index + 3] = vertices[index + 0] + new Vector3(segmentWidth, 0, 0); // BR
5208 
5209  // Middle Part of the Underline
5210  vertices[index + 4] = vertices[index + 3]; // BL
5211  vertices[index + 5] = vertices[index + 2]; // TL
5212  vertices[index + 6] = end + new Vector3(-segmentWidth, m_padding * maxScale, 0); // TR
5213  vertices[index + 7] = end + new Vector3(-segmentWidth, -(underlineThickness + m_padding) * maxScale, 0); // BR
5214 
5215  // End Part of the Underline
5216  vertices[index + 8] = vertices[index + 7]; // BL
5217  vertices[index + 9] = vertices[index + 6]; // TL
5218  vertices[index + 10] = end + new Vector3(0, m_padding * maxScale, 0); // TR
5219  vertices[index + 11] = end + new Vector3(0, -(underlineThickness + m_padding) * maxScale, 0); // BR
5220  #endregion
5221 
5222  // UNDERLINE UV0
5223  #region HANDLE UV0
5224  Vector2[] uvs0 = m_textInfo.meshInfo[0].uvs0;
5225 
5226  // Calculate UV required to setup the 3 Quads for the Underline.
5227  Vector2 uv0 = new Vector2((m_cached_Underline_GlyphInfo.x - startPadding) / m_fontAsset.fontInfo.AtlasWidth, 1 - (m_cached_Underline_GlyphInfo.y + m_padding + m_cached_Underline_GlyphInfo.height) / m_fontAsset.fontInfo.AtlasHeight); // bottom left
5228  Vector2 uv1 = new Vector2(uv0.x, 1 - (m_cached_Underline_GlyphInfo.y - m_padding) / m_fontAsset.fontInfo.AtlasHeight); // top left
5229  Vector2 uv2 = new Vector2((m_cached_Underline_GlyphInfo.x - startPadding + m_cached_Underline_GlyphInfo.width / 2) / m_fontAsset.fontInfo.AtlasWidth, uv1.y); // Mid Top Left
5230  Vector2 uv3 = new Vector2(uv2.x, uv0.y); // Mid Bottom Left
5231  Vector2 uv4 = new Vector2((m_cached_Underline_GlyphInfo.x + endPadding + m_cached_Underline_GlyphInfo.width / 2) / m_fontAsset.fontInfo.AtlasWidth, uv1.y); // Mid Top Right
5232  Vector2 uv5 = new Vector2(uv4.x, uv0.y); // Mid Bottom right
5233  Vector2 uv6 = new Vector2((m_cached_Underline_GlyphInfo.x + endPadding + m_cached_Underline_GlyphInfo.width) / m_fontAsset.fontInfo.AtlasWidth, uv1.y); // End Part - Bottom Right
5234  Vector2 uv7 = new Vector2(uv6.x, uv0.y); // End Part - Top Right
5235 
5236  // Left Part of the Underline
5237  uvs0[0 + index] = uv0; // BL
5238  uvs0[1 + index] = uv1; // TL
5239  uvs0[2 + index] = uv2; // TR
5240  uvs0[3 + index] = uv3; // BR
5241 
5242  // Middle Part of the Underline
5243  uvs0[4 + index] = new Vector2(uv2.x - uv2.x * 0.001f, uv0.y);
5244  uvs0[5 + index] = new Vector2(uv2.x - uv2.x * 0.001f, uv1.y);
5245  uvs0[6 + index] = new Vector2(uv2.x + uv2.x * 0.001f, uv1.y);
5246  uvs0[7 + index] = new Vector2(uv2.x + uv2.x * 0.001f, uv0.y);
5247 
5248  // Right Part of the Underline
5249  uvs0[8 + index] = uv5;
5250  uvs0[9 + index] = uv4;
5251  uvs0[10 + index] = uv6;
5252  uvs0[11 + index] = uv7;
5253  #endregion
5254 
5255  // UNDERLINE UV2
5256  #region HANDLE UV2 - SDF SCALE
5257  // UV1 contains Face / Border UV layout.
5258  float min_UvX = 0;
5259  float max_UvX = (vertices[index + 2].x - start.x) / (end.x - start.x);
5260 
5261  //Calculate the xScale or how much the UV's are getting stretched on the X axis for the middle section of the underline.
5262  float xScale = Mathf.Abs(sdfScale);
5263 
5264  Vector2[] uvs2 = m_textInfo.meshInfo[0].uvs2;
5265 
5266  uvs2[0 + index] = PackUV(0, 0, xScale);
5267  uvs2[1 + index] = PackUV(0, 1, xScale);
5268  uvs2[2 + index] = PackUV(max_UvX, 1, xScale);
5269  uvs2[3 + index] = PackUV(max_UvX, 0, xScale);
5270 
5271  min_UvX = (vertices[index + 4].x - start.x) / (end.x - start.x);
5272  max_UvX = (vertices[index + 6].x - start.x) / (end.x - start.x);
5273 
5274  uvs2[4 + index] = PackUV(min_UvX, 0, xScale);
5275  uvs2[5 + index] = PackUV(min_UvX, 1, xScale);
5276  uvs2[6 + index] = PackUV(max_UvX, 1, xScale);
5277  uvs2[7 + index] = PackUV(max_UvX, 0, xScale);
5278 
5279  min_UvX = (vertices[index + 8].x - start.x) / (end.x - start.x);
5280  max_UvX = (vertices[index + 6].x - start.x) / (end.x - start.x);
5281 
5282  uvs2[8 + index] = PackUV(min_UvX, 0, xScale);
5283  uvs2[9 + index] = PackUV(min_UvX, 1, xScale);
5284  uvs2[10 + index] = PackUV(1, 1, xScale);
5285  uvs2[11 + index] = PackUV(1, 0, xScale);
5286  #endregion
5287 
5288  // UNDERLINE VERTEX COLORS
5289  #region
5290  // Alpha is the lower of the vertex color or tag color alpha used.
5291  underlineColor.a = m_fontColor32.a < underlineColor.a ? (byte)(m_fontColor32.a) : (byte)(underlineColor.a);
5292 
5293  Color32[] colors32 = m_textInfo.meshInfo[0].colors32;
5294  colors32[0 + index] = underlineColor;
5295  colors32[1 + index] = underlineColor;
5296  colors32[2 + index] = underlineColor;
5297  colors32[3 + index] = underlineColor;
5298 
5299  colors32[4 + index] = underlineColor;
5300  colors32[5 + index] = underlineColor;
5301  colors32[6 + index] = underlineColor;
5302  colors32[7 + index] = underlineColor;
5303 
5304  colors32[8 + index] = underlineColor;
5305  colors32[9 + index] = underlineColor;
5306  colors32[10 + index] = underlineColor;
5307  colors32[11 + index] = underlineColor;
5308  #endregion
5309 
5310  index += 12;
5311  }
5312 
5313 
5314  protected virtual void DrawTextHighlight(Vector3 start, Vector3 end, ref int index, Color32 highlightColor)
5315  {
5316  if (m_cached_Underline_GlyphInfo == null)
5317  {
5318  if (!TMP_Settings.warningsDisabled) Debug.LogWarning("Unable to add underline since the Font Asset doesn't contain the underline character.", this);
5319  return;
5320  }
5321 
5322  int verticesCount = index + 4;
5323  // Check to make sure our current mesh buffer allocations can hold these new Quads.
5324  if (verticesCount > m_textInfo.meshInfo[0].vertices.Length)
5325  {
5326  // Resize Mesh Buffers
5327  m_textInfo.meshInfo[0].ResizeMeshInfo(verticesCount / 4);
5328  }
5329 
5330  // UNDERLINE VERTICES FOR (3) LINE SEGMENTS
5331  #region HIGHLIGHT VERTICES
5332  Vector3[] vertices = m_textInfo.meshInfo[0].vertices;
5333 
5334  // Front Part of the Underline
5335  vertices[index + 0] = start; // BL
5336  vertices[index + 1] = new Vector3(start.x, end.y, 0); // TL
5337  vertices[index + 2] = end; // TR
5338  vertices[index + 3] = new Vector3(end.x, start.y, 0); // BR
5339  #endregion
5340 
5341  // UNDERLINE UV0
5342  #region HANDLE UV0
5343  Vector2[] uvs0 = m_textInfo.meshInfo[0].uvs0;
5344 
5345  // Calculate UV required to setup the 3 Quads for the Underline.
5346  Vector2 uv0 = new Vector2((m_cached_Underline_GlyphInfo.x + m_cached_Underline_GlyphInfo.width / 2) / m_fontAsset.fontInfo.AtlasWidth, 1 - (m_cached_Underline_GlyphInfo.y + m_cached_Underline_GlyphInfo.height / 2) / m_fontAsset.fontInfo.AtlasHeight); // bottom left
5347  //Vector2 uv1 = new Vector2(uv0.x, uv0.y); // top left
5348  //Vector2 uv2 = new Vector2(uv0.x, uv0.y); // Top Right
5349  //Vector2 uv3 = new Vector2(uv2.x, uv0.y); // Bottom Right
5350 
5351  // Left Part of the Underline
5352  uvs0[0 + index] = uv0; // BL
5353  uvs0[1 + index] = uv0; // TL
5354  uvs0[2 + index] = uv0; // TR
5355  uvs0[3 + index] = uv0; // BR
5356  #endregion
5357 
5358  // UNDERLINE UV2
5359  #region HANDLE UV2 - SDF SCALE
5360  // UV1 contains Face / Border UV layout.
5361  //float min_UvX = 0;
5362  //float max_UvX = (vertices[index + 2].x - start.x) / (end.x - start.x);
5363 
5365  //float xScale = 0; // Mathf.Abs(sdfScale);
5366 
5367  Vector2[] uvs2 = m_textInfo.meshInfo[0].uvs2;
5368  Vector2 customUV = new Vector2(0, 1);
5369  uvs2[0 + index] = customUV; // PackUV(-0.2f, -0.2f, xScale);
5370  uvs2[1 + index] = customUV; // PackUV(-0.2f, -0.1f, xScale);
5371  uvs2[2 + index] = customUV; // PackUV(-0.1f, -0.1f, xScale);
5372  uvs2[3 + index] = customUV; // PackUV(-0.1f, -0.2f, xScale);
5373  #endregion
5374 
5375  // HIGHLIGHT VERTEX COLORS
5376  #region
5377  // Alpha is the lower of the vertex color or tag color alpha used.
5378  highlightColor.a = m_fontColor32.a < highlightColor.a ? m_fontColor32.a : highlightColor.a;
5379 
5380  Color32[] colors32 = m_textInfo.meshInfo[0].colors32;
5381  colors32[0 + index] = highlightColor;
5382  colors32[1 + index] = highlightColor;
5383  colors32[2 + index] = highlightColor;
5384  colors32[3 + index] = highlightColor;
5385  #endregion
5386 
5387  index += 4;
5388  }
5389 
5390 
5394  protected void LoadDefaultSettings()
5395  {
5396  if (m_text == null || m_isWaitingOnResourceLoad)
5397  {
5399  autoSizeTextContainer = true;
5400  else
5401  {
5402  m_rectTransform = this.rectTransform;
5403 
5404  if (GetType() == typeof(TextMeshPro))
5405  m_rectTransform.sizeDelta = TMP_Settings.defaultTextMeshProTextContainerSize;
5406  else
5407  m_rectTransform.sizeDelta = TMP_Settings.defaultTextMeshProUITextContainerSize;
5408  }
5409 
5410  m_enableWordWrapping = TMP_Settings.enableWordWrapping;
5411  m_enableKerning = TMP_Settings.enableKerning;
5412  m_enableExtraPadding = TMP_Settings.enableExtraPadding;
5413  m_tintAllSprites = TMP_Settings.enableTintAllSprites;
5414  m_parseCtrlCharacters = TMP_Settings.enableParseEscapeCharacters;
5415  m_fontSize = m_fontSizeBase = TMP_Settings.defaultFontSize;
5416  m_fontSizeMin = m_fontSize * TMP_Settings.defaultTextAutoSizingMinRatio;
5417  m_fontSizeMax = m_fontSize * TMP_Settings.defaultTextAutoSizingMaxRatio;
5418  m_isAlignmentEnumConverted = true;
5419  m_isWaitingOnResourceLoad = false;
5420  }
5421  else if (m_isAlignmentEnumConverted == false)
5422  {
5423  // Convert TextAlignmentOptions enumerations.
5424  m_isAlignmentEnumConverted = true;
5425  m_textAlignment = TMP_Compatibility.ConvertTextAlignmentEnumValues(m_textAlignment);
5426  }
5427  }
5428 
5429 
5434  protected void GetSpecialCharacters(TMP_FontAsset fontAsset)
5435  {
5436  // Check & Assign Underline Character for use with the Underline tag.
5437  if (!fontAsset.characterDictionary.TryGetValue(95, out m_cached_Underline_GlyphInfo)) //95
5438  {
5439  // Check fallback fonts
5440  // TODO
5441  }
5442 
5443  // Check & Assign Underline Character for use with the Underline tag.
5444  if (!fontAsset.characterDictionary.TryGetValue(8230, out m_cached_Ellipsis_GlyphInfo)) //95
5445  {
5446  // Check fallback fonts
5447  // TODO
5448  }
5449  }
5450 
5451 
5459  protected void ReplaceTagWithCharacter(int[] chars, int insertionIndex, int tagLength, char c)
5460  {
5461  chars[insertionIndex] = c;
5462 
5463  for (int i = insertionIndex + tagLength; i < chars.Length; i++)
5464  {
5465  chars[i - 3] = chars[i];
5466  }
5467  }
5468 
5469 
5474  //protected int GetMaterialReferenceForFontWeight()
5475  //{
5476  // //bool isItalic = (m_style & FontStyles.Italic) == FontStyles.Italic || (m_fontStyle & FontStyles.Italic) == FontStyles.Italic;
5477 
5478  // m_currentMaterialIndex = MaterialReference.AddMaterialReference(m_currentFontAsset.fontWeights[0].italicTypeface.material, m_currentFontAsset.fontWeights[0].italicTypeface, m_materialReferences, m_materialReferenceIndexLookup);
5479 
5480  // return 0;
5481  //}
5482 
5483 
5489  {
5490  bool isItalic = (m_style & FontStyles.Italic) == FontStyles.Italic || (m_fontStyle & FontStyles.Italic) == FontStyles.Italic;
5491 
5492  TMP_FontAsset fontAsset = null;
5493 
5494  int weightIndex = fontWeight / 100;
5495 
5496  if (isItalic)
5497  fontAsset = m_currentFontAsset.fontWeights[weightIndex].italicTypeface;
5498  else
5499  fontAsset = m_currentFontAsset.fontWeights[weightIndex].regularTypeface;
5500 
5501  return fontAsset;
5502  }
5503 
5504 
5509  protected virtual void SetActiveSubMeshes(bool state) { }
5510 
5511 
5515  protected virtual void ClearSubMeshObjects() { }
5516 
5517 
5521  public virtual void ClearMesh() { }
5522 
5523 
5527  public virtual void ClearMesh(bool uploadGeometry) { }
5528 
5529 
5534  public virtual string GetParsedText()
5535  {
5536  if (m_textInfo == null)
5537  return string.Empty;
5538 
5539  int characterCount = m_textInfo.characterCount;
5540 
5541  // TODO - Could implement some static buffer pool shared by all instances of TMP objects.
5542  char[] buffer = new char[characterCount];
5543 
5544  for (int i = 0; i < characterCount && i < m_textInfo.characterInfo.Length; i++)
5545  {
5546  buffer[i] = m_textInfo.characterInfo[i].character;
5547  }
5548 
5549  return new string(buffer);
5550  }
5551 
5552 
5560  //protected Vector2 PackUV(float x, float y, float scale)
5561  //{
5562  // Vector2 output;
5563 
5564  // output.x = Mathf.Floor(x * 4095);
5565  // output.y = Mathf.Floor(y * 4095);
5566 
5567  // output.x = (output.x * 4096) + output.y;
5568  // output.y = scale;
5569 
5570  // return output;
5571  //}
5572 
5580  protected Vector2 PackUV(float x, float y, float scale)
5581  {
5582  Vector2 output;
5583 
5584  output.x = (int)(x * 511);
5585  output.y = (int)(y * 511);
5586 
5587  output.x = (output.x * 4096) + output.y;
5588  output.y = scale;
5589 
5590  return output;
5591  }
5592 
5593 
5600  protected float PackUV(float x, float y)
5601  {
5602  double x0 = (int)(x * 511);
5603  double y0 = (int)(y * 511);
5604 
5605  return (float)((x0 * 4096) + y0);
5606  }
5607 
5608 
5616  //protected Vector2 PackUV(float x, float y, float scale)
5617  //{
5618  // Vector2 output;
5619 
5620  // output.x = Mathf.Floor(x * 4095);
5621  // output.y = Mathf.Floor(y * 4095);
5622 
5623  // return new Vector2((output.x * 4096) + output.y, scale);
5624  //}
5625 
5626 
5633  //protected float PackUV(float x, float y)
5634  //{
5635  // x = (x % 5) / 5;
5636  // y = (y % 5) / 5;
5637 
5638  // return Mathf.Round(x * 4096) + y;
5639  //}
5640 
5641 
5647  protected int HexToInt(char hex)
5648  {
5649  switch (hex)
5650  {
5651  case '0': return 0;
5652  case '1': return 1;
5653  case '2': return 2;
5654  case '3': return 3;
5655  case '4': return 4;
5656  case '5': return 5;
5657  case '6': return 6;
5658  case '7': return 7;
5659  case '8': return 8;
5660  case '9': return 9;
5661  case 'A': return 10;
5662  case 'B': return 11;
5663  case 'C': return 12;
5664  case 'D': return 13;
5665  case 'E': return 14;
5666  case 'F': return 15;
5667  case 'a': return 10;
5668  case 'b': return 11;
5669  case 'c': return 12;
5670  case 'd': return 13;
5671  case 'e': return 14;
5672  case 'f': return 15;
5673  }
5674  return 15;
5675  }
5676 
5677 
5683  protected int GetUTF16(string text, int i)
5684  {
5685  int unicode = 0;
5686  unicode += HexToInt(text[i]) << 12;
5687  unicode += HexToInt(text[i + 1]) << 8;
5688  unicode += HexToInt(text[i + 2]) << 4;
5689  unicode += HexToInt(text[i + 3]);
5690  return unicode;
5691  }
5692 
5698  protected int GetUTF16(StringBuilder text, int i)
5699  {
5700  int unicode = 0;
5701  unicode += HexToInt(text[i]) << 12;
5702  unicode += HexToInt(text[i + 1]) << 8;
5703  unicode += HexToInt(text[i + 2]) << 4;
5704  unicode += HexToInt(text[i + 3]);
5705  return unicode;
5706  }
5707 
5708 
5714  protected int GetUTF32(string text, int i)
5715  {
5716  int unicode = 0;
5717  unicode += HexToInt(text[i]) << 30;
5718  unicode += HexToInt(text[i + 1]) << 24;
5719  unicode += HexToInt(text[i + 2]) << 20;
5720  unicode += HexToInt(text[i + 3]) << 16;
5721  unicode += HexToInt(text[i + 4]) << 12;
5722  unicode += HexToInt(text[i + 5]) << 8;
5723  unicode += HexToInt(text[i + 6]) << 4;
5724  unicode += HexToInt(text[i + 7]);
5725  return unicode;
5726  }
5727 
5733  protected int GetUTF32(StringBuilder text, int i)
5734  {
5735  int unicode = 0;
5736  unicode += HexToInt(text[i]) << 30;
5737  unicode += HexToInt(text[i + 1]) << 24;
5738  unicode += HexToInt(text[i + 2]) << 20;
5739  unicode += HexToInt(text[i + 3]) << 16;
5740  unicode += HexToInt(text[i + 4]) << 12;
5741  unicode += HexToInt(text[i + 5]) << 8;
5742  unicode += HexToInt(text[i + 6]) << 4;
5743  unicode += HexToInt(text[i + 7]);
5744  return unicode;
5745  }
5746 
5747 
5754  protected Color32 HexCharsToColor(char[] hexChars, int tagCount)
5755  {
5756  if (tagCount == 4)
5757  {
5758  byte r = (byte)(HexToInt(hexChars[1]) * 16 + HexToInt(hexChars[1]));
5759  byte g = (byte)(HexToInt(hexChars[2]) * 16 + HexToInt(hexChars[2]));
5760  byte b = (byte)(HexToInt(hexChars[3]) * 16 + HexToInt(hexChars[3]));
5761 
5762  return new Color32(r, g, b, 255);
5763  }
5764  else if (tagCount == 5)
5765  {
5766  byte r = (byte)(HexToInt(hexChars[1]) * 16 + HexToInt(hexChars[1]));
5767  byte g = (byte)(HexToInt(hexChars[2]) * 16 + HexToInt(hexChars[2]));
5768  byte b = (byte)(HexToInt(hexChars[3]) * 16 + HexToInt(hexChars[3]));
5769  byte a = (byte)(HexToInt(hexChars[4]) * 16 + HexToInt(hexChars[4]));
5770 
5771  return new Color32(r, g, b, a);
5772  }
5773  else if (tagCount == 7)
5774  {
5775  byte r = (byte)(HexToInt(hexChars[1]) * 16 + HexToInt(hexChars[2]));
5776  byte g = (byte)(HexToInt(hexChars[3]) * 16 + HexToInt(hexChars[4]));
5777  byte b = (byte)(HexToInt(hexChars[5]) * 16 + HexToInt(hexChars[6]));
5778 
5779  return new Color32(r, g, b, 255);
5780  }
5781  else if (tagCount == 9)
5782  {
5783  byte r = (byte)(HexToInt(hexChars[1]) * 16 + HexToInt(hexChars[2]));
5784  byte g = (byte)(HexToInt(hexChars[3]) * 16 + HexToInt(hexChars[4]));
5785  byte b = (byte)(HexToInt(hexChars[5]) * 16 + HexToInt(hexChars[6]));
5786  byte a = (byte)(HexToInt(hexChars[7]) * 16 + HexToInt(hexChars[8]));
5787 
5788  return new Color32(r, g, b, a);
5789  }
5790  else if (tagCount == 10)
5791  {
5792  byte r = (byte)(HexToInt(hexChars[7]) * 16 + HexToInt(hexChars[7]));
5793  byte g = (byte)(HexToInt(hexChars[8]) * 16 + HexToInt(hexChars[8]));
5794  byte b = (byte)(HexToInt(hexChars[9]) * 16 + HexToInt(hexChars[9]));
5795 
5796  return new Color32(r, g, b, 255);
5797  }
5798  else if (tagCount == 11)
5799  {
5800  byte r = (byte)(HexToInt(hexChars[7]) * 16 + HexToInt(hexChars[7]));
5801  byte g = (byte)(HexToInt(hexChars[8]) * 16 + HexToInt(hexChars[8]));
5802  byte b = (byte)(HexToInt(hexChars[9]) * 16 + HexToInt(hexChars[9]));
5803  byte a = (byte)(HexToInt(hexChars[10]) * 16 + HexToInt(hexChars[10]));
5804 
5805  return new Color32(r, g, b, a);
5806  }
5807  else if (tagCount == 13)
5808  {
5809  byte r = (byte)(HexToInt(hexChars[7]) * 16 + HexToInt(hexChars[8]));
5810  byte g = (byte)(HexToInt(hexChars[9]) * 16 + HexToInt(hexChars[10]));
5811  byte b = (byte)(HexToInt(hexChars[11]) * 16 + HexToInt(hexChars[12]));
5812 
5813  return new Color32(r, g, b, 255);
5814  }
5815  else if (tagCount == 15)
5816  {
5817  byte r = (byte)(HexToInt(hexChars[7]) * 16 + HexToInt(hexChars[8]));
5818  byte g = (byte)(HexToInt(hexChars[9]) * 16 + HexToInt(hexChars[10]));
5819  byte b = (byte)(HexToInt(hexChars[11]) * 16 + HexToInt(hexChars[12]));
5820  byte a = (byte)(HexToInt(hexChars[13]) * 16 + HexToInt(hexChars[14]));
5821 
5822  return new Color32(r, g, b, a);
5823  }
5824 
5825  return new Color32(255, 255, 255, 255);
5826  }
5827 
5828 
5836  protected Color32 HexCharsToColor(char[] hexChars, int startIndex, int length)
5837  {
5838  if (length == 7)
5839  {
5840  byte r = (byte)(HexToInt(hexChars[startIndex + 1]) * 16 + HexToInt(hexChars[startIndex + 2]));
5841  byte g = (byte)(HexToInt(hexChars[startIndex + 3]) * 16 + HexToInt(hexChars[startIndex + 4]));
5842  byte b = (byte)(HexToInt(hexChars[startIndex + 5]) * 16 + HexToInt(hexChars[startIndex + 6]));
5843 
5844  return new Color32(r, g, b, 255);
5845  }
5846  else if (length == 9)
5847  {
5848  byte r = (byte)(HexToInt(hexChars[startIndex + 1]) * 16 + HexToInt(hexChars[startIndex + 2]));
5849  byte g = (byte)(HexToInt(hexChars[startIndex + 3]) * 16 + HexToInt(hexChars[startIndex + 4]));
5850  byte b = (byte)(HexToInt(hexChars[startIndex + 5]) * 16 + HexToInt(hexChars[startIndex + 6]));
5851  byte a = (byte)(HexToInt(hexChars[startIndex + 7]) * 16 + HexToInt(hexChars[startIndex + 8]));
5852 
5853  return new Color32(r, g, b, a);
5854  }
5855 
5856  return s_colorWhite;
5857  }
5858 
5859 
5868  int GetAttributeParameters(char[] chars, int startIndex, int length, ref float[] parameters)
5869  {
5870  int endIndex = startIndex;
5871  int attributeCount = 0;
5872 
5873  while (endIndex < startIndex + length)
5874  {
5875  parameters[attributeCount] = ConvertToFloat(chars, startIndex, length, out endIndex);
5876 
5877  length -= (endIndex - startIndex) + 1;
5878  startIndex = endIndex + 1;
5879 
5880  attributeCount += 1;
5881  }
5882 
5883  return attributeCount;
5884  }
5885 
5886 
5894  protected float ConvertToFloat(char[] chars, int startIndex, int length)
5895  {
5896  int lastIndex = 0;
5897  return ConvertToFloat(chars, startIndex, length, out lastIndex);
5898  }
5899 
5900 
5909  protected float ConvertToFloat(char[] chars, int startIndex, int length, out int lastIndex)
5910  {
5911  if (startIndex == 0) { lastIndex = 0; return -9999; }
5912  int endIndex = startIndex + length;
5913 
5914  bool isIntegerValue = true;
5915  float decimalPointMultiplier = 0;
5916 
5917  // Set value multiplier checking the first character to determine if we are using '+' or '-'
5918  int valueSignMultiplier = 1;
5919  if (chars[startIndex] == '+')
5920  {
5921  valueSignMultiplier = 1;
5922  startIndex += 1;
5923  }
5924  else if (chars[startIndex] == '-')
5925  {
5926  valueSignMultiplier = -1;
5927  startIndex += 1;
5928  }
5929 
5930  float value = 0;
5931 
5932  for (int i = startIndex; i < endIndex; i++)
5933  {
5934  uint c = chars[i];
5935 
5936  if (c >= '0' && c <= '9' || c == '.')
5937  {
5938  if (c == '.')
5939  {
5940  isIntegerValue = false;
5941  decimalPointMultiplier = 0.1f;
5942  continue;
5943  }
5944 
5945  //Calculate integer and floating point value
5946  if (isIntegerValue)
5947  value = value * 10 + (c - 48) * valueSignMultiplier;
5948  else
5949  {
5950  value = value + (c - 48) * decimalPointMultiplier * valueSignMultiplier;
5951  decimalPointMultiplier *= 0.1f;
5952  }
5953 
5954  continue;
5955  }
5956  else if (c == ',')
5957  {
5958  if (i + 1 < endIndex && chars[i + 1] == ' ')
5959  lastIndex = i + 1;
5960  else
5961  lastIndex = i;
5962 
5963  return value;
5964  }
5965  }
5966 
5967  lastIndex = endIndex;
5968  return value;
5969  }
5970 
5971 
5979  protected bool ValidateHtmlTag(int[] chars, int startIndex, out int endIndex)
5980  {
5981  int tagCharCount = 0;
5982  byte attributeFlag = 0;
5983 
5984  TagUnits tagUnits = TagUnits.Pixels;
5985  TagType tagType = TagType.None;
5986 
5987  int attributeIndex = 0;
5988  m_xmlAttribute[attributeIndex].nameHashCode = 0;
5989  m_xmlAttribute[attributeIndex].valueType = TagType.None;
5990  m_xmlAttribute[attributeIndex].valueHashCode = 0;
5991  m_xmlAttribute[attributeIndex].valueStartIndex = 0;
5992  m_xmlAttribute[attributeIndex].valueLength = 0;
5993 
5994  // Clear attribute name hash codes
5995  m_xmlAttribute[1].nameHashCode = 0;
5996  m_xmlAttribute[2].nameHashCode = 0;
5997  m_xmlAttribute[3].nameHashCode = 0;
5998  m_xmlAttribute[4].nameHashCode = 0;
5999 
6000  endIndex = startIndex;
6001  bool isTagSet = false;
6002  bool isValidHtmlTag = false;
6003 
6004  for (int i = startIndex; i < chars.Length && chars[i] != 0 && tagCharCount < m_htmlTag.Length && chars[i] != 60; i++)
6005  {
6006  if (chars[i] == 62) // ASCII Code of End HTML tag '>'
6007  {
6008  isValidHtmlTag = true;
6009  endIndex = i;
6010  m_htmlTag[tagCharCount] = (char)0;
6011  break;
6012  }
6013 
6014  m_htmlTag[tagCharCount] = (char)chars[i];
6015  tagCharCount += 1;
6016 
6017  if (attributeFlag == 1)
6018  {
6019  if (tagType == TagType.None)
6020  {
6021  // Check for attribute type
6022  if (chars[i] == 43 || chars[i] == 45 || chars[i] == 46 || (chars[i] >= '0' && chars[i] <= '9'))
6023  {
6024  tagType = TagType.NumericalValue;
6025  m_xmlAttribute[attributeIndex].valueType = TagType.NumericalValue;
6026  m_xmlAttribute[attributeIndex].valueStartIndex = tagCharCount - 1;
6027  m_xmlAttribute[attributeIndex].valueLength += 1;
6028  }
6029  else if (chars[i] == 35)
6030  {
6031  tagType = TagType.ColorValue;
6032  m_xmlAttribute[attributeIndex].valueType = TagType.ColorValue;
6033  m_xmlAttribute[attributeIndex].valueStartIndex = tagCharCount - 1;
6034  m_xmlAttribute[attributeIndex].valueLength += 1;
6035  }
6036  else if (chars[i] == 34)
6037  {
6038  tagType = TagType.StringValue;
6039  m_xmlAttribute[attributeIndex].valueType = TagType.StringValue;
6040  m_xmlAttribute[attributeIndex].valueStartIndex = tagCharCount;
6041  }
6042  else
6043  {
6044  tagType = TagType.StringValue;
6045  m_xmlAttribute[attributeIndex].valueType = TagType.StringValue;
6046  m_xmlAttribute[attributeIndex].valueStartIndex = tagCharCount - 1;
6047  m_xmlAttribute[attributeIndex].valueHashCode = (m_xmlAttribute[attributeIndex].valueHashCode << 5) + m_xmlAttribute[attributeIndex].valueHashCode ^ chars[i];
6048  m_xmlAttribute[attributeIndex].valueLength += 1;
6049  }
6050  }
6051  else
6052  {
6053  if (tagType == TagType.NumericalValue)
6054  {
6055  // Check for termination of numerical value.
6056  if (chars[i] == 112 || chars[i] == 101 || chars[i] == 37 || chars[i] == 32)
6057  {
6058  attributeFlag = 2;
6059  tagType = TagType.None;
6060  attributeIndex += 1;
6061  m_xmlAttribute[attributeIndex].nameHashCode = 0;
6062  m_xmlAttribute[attributeIndex].valueType = TagType.None;
6063  m_xmlAttribute[attributeIndex].valueHashCode = 0;
6064  m_xmlAttribute[attributeIndex].valueStartIndex = 0;
6065  m_xmlAttribute[attributeIndex].valueLength = 0;
6066 
6067  if (chars[i] == 101)
6068  tagUnits = TagUnits.FontUnits;
6069  else if (chars[i] == 37)
6070  tagUnits = TagUnits.Percentage;
6071  }
6072  else if (attributeFlag != 2)
6073  {
6074  m_xmlAttribute[attributeIndex].valueLength += 1;
6075  }
6076  }
6077  else if (tagType == TagType.ColorValue)
6078  {
6079  if (chars[i] != 32)
6080  {
6081  m_xmlAttribute[attributeIndex].valueLength += 1;
6082  }
6083  else
6084  {
6085  attributeFlag = 2;
6086  tagType = TagType.None;
6087  attributeIndex += 1;
6088  m_xmlAttribute[attributeIndex].nameHashCode = 0;
6089  m_xmlAttribute[attributeIndex].valueType = TagType.None;
6090  m_xmlAttribute[attributeIndex].valueHashCode = 0;
6091  m_xmlAttribute[attributeIndex].valueStartIndex = 0;
6092  m_xmlAttribute[attributeIndex].valueLength = 0;
6093  }
6094  }
6095  else if (tagType == TagType.StringValue)
6096  {
6097  // Compute HashCode value for the named tag.
6098  if (chars[i] != 34)
6099  {
6100  m_xmlAttribute[attributeIndex].valueHashCode = (m_xmlAttribute[attributeIndex].valueHashCode << 5) + m_xmlAttribute[attributeIndex].valueHashCode ^ chars[i];
6101  m_xmlAttribute[attributeIndex].valueLength += 1;
6102  }
6103  else
6104  {
6105  //m_xmlAttribute[attributeIndex].valueHashCode = -1;
6106  attributeFlag = 2;
6107  tagType = TagType.None;
6108  attributeIndex += 1;
6109  m_xmlAttribute[attributeIndex].nameHashCode = 0;
6110  m_xmlAttribute[attributeIndex].valueType = TagType.None;
6111  m_xmlAttribute[attributeIndex].valueHashCode = 0;
6112  m_xmlAttribute[attributeIndex].valueStartIndex = 0;
6113  m_xmlAttribute[attributeIndex].valueLength = 0;
6114  }
6115  }
6116  }
6117  }
6118 
6119 
6120  if (chars[i] == 61) // '='
6121  attributeFlag = 1;
6122 
6123  // Compute HashCode for the name of the attribute
6124  if (attributeFlag == 0 && chars[i] == 32)
6125  {
6126  if (isTagSet) return false;
6127 
6128  isTagSet = true;
6129  attributeFlag = 2;
6130 
6131  tagType = TagType.None;
6132  attributeIndex += 1;
6133  m_xmlAttribute[attributeIndex].nameHashCode = 0;
6134  m_xmlAttribute[attributeIndex].valueType = TagType.None;
6135  m_xmlAttribute[attributeIndex].valueHashCode = 0;
6136  m_xmlAttribute[attributeIndex].valueStartIndex = 0;
6137  m_xmlAttribute[attributeIndex].valueLength = 0;
6138  }
6139 
6140  if (attributeFlag == 0)
6141  m_xmlAttribute[attributeIndex].nameHashCode = (m_xmlAttribute[attributeIndex].nameHashCode << 3) - m_xmlAttribute[attributeIndex].nameHashCode + chars[i];
6142 
6143  if (attributeFlag == 2 && chars[i] == 32)
6144  attributeFlag = 0;
6145 
6146  }
6147 
6148  if (!isValidHtmlTag)
6149  {
6150  return false;
6151  }
6152 
6153  //Debug.Log("Tag is [" + m_htmlTag.ArrayToString() + "]. Tag HashCode: " + m_xmlAttribute[0].nameHashCode + " Tag Value HashCode: " + m_xmlAttribute[0].valueHashCode + " Attribute 1 HashCode: " + m_xmlAttribute[1].nameHashCode + " Value HashCode: " + m_xmlAttribute[1].valueHashCode);
6154  //for (int i = 0; i < attributeIndex + 1; i++)
6155  // Debug.Log("Tag [" + i + "] with HashCode: " + m_xmlAttribute[i].nameHashCode + " has value of [" + new string(m_htmlTag, m_xmlAttribute[i].valueStartIndex, m_xmlAttribute[i].valueLength) + "] Numerical Value: " + ConvertToFloat(m_htmlTag, m_xmlAttribute[i].valueStartIndex, m_xmlAttribute[i].valueLength));
6156 
6157 
6158  // Special handling of the no parsing tag </noparse> </NOPARSE> tag
6159  if (tag_NoParsing && (m_xmlAttribute[0].nameHashCode != 53822163 && m_xmlAttribute[0].nameHashCode != 49429939))
6160  return false;
6161  else if (m_xmlAttribute[0].nameHashCode == 53822163 || m_xmlAttribute[0].nameHashCode == 49429939)
6162  {
6163  tag_NoParsing = false;
6164  return true;
6165  }
6166 
6167  // Color <#FFF> 3 Hex values (short form)
6168  if (m_htmlTag[0] == 35 && tagCharCount == 4)
6169  {
6170  m_htmlColor = HexCharsToColor(m_htmlTag, tagCharCount);
6171  m_colorStack.Add(m_htmlColor);
6172  return true;
6173  }
6174  // Color <#FFF7> 4 Hex values with alpha (short form)
6175  else if (m_htmlTag[0] == 35 && tagCharCount == 5)
6176  {
6177  m_htmlColor = HexCharsToColor(m_htmlTag, tagCharCount);
6178  m_colorStack.Add(m_htmlColor);
6179  return true;
6180  }
6181  // Color <#FF00FF>
6182  else if (m_htmlTag[0] == 35 && tagCharCount == 7) // if Tag begins with # and contains 7 characters.
6183  {
6184  m_htmlColor = HexCharsToColor(m_htmlTag, tagCharCount);
6185  m_colorStack.Add(m_htmlColor);
6186  return true;
6187  }
6188  // Color <#FF00FF00> with alpha
6189  else if (m_htmlTag[0] == 35 && tagCharCount == 9) // if Tag begins with # and contains 9 characters.
6190  {
6191  m_htmlColor = HexCharsToColor(m_htmlTag, tagCharCount);
6192  m_colorStack.Add(m_htmlColor);
6193  return true;
6194  }
6195  else
6196  {
6197  float value = 0;
6198 
6199  switch (m_xmlAttribute[0].nameHashCode)
6200  {
6201  case 98: // <b>
6202  case 66: // <B>
6203  m_style |= FontStyles.Bold;
6204  m_fontStyleStack.Add(FontStyles.Bold);
6205 
6206  m_fontWeightInternal = 700;
6207  m_fontWeightStack.Add(700);
6208  return true;
6209  case 427: // </b>
6210  case 395: // </B>
6211  if ((m_fontStyle & FontStyles.Bold) != FontStyles.Bold)
6212  {
6213  m_fontWeightInternal = m_fontWeightStack.Remove();
6214 
6215  if (m_fontStyleStack.Remove(FontStyles.Bold) == 0)
6216  m_style &= ~FontStyles.Bold;
6217  }
6218  return true;
6219  case 105: // <i>
6220  case 73: // <I>
6221  m_style |= FontStyles.Italic;
6222  m_fontStyleStack.Add(FontStyles.Italic);
6223  return true;
6224  case 434: // </i>
6225  case 402: // </I>
6226  if (m_fontStyleStack.Remove(FontStyles.Italic) == 0)
6227  m_style &= ~FontStyles.Italic;
6228 
6229  return true;
6230  case 115: // <s>
6231  case 83: // <S>
6232  m_style |= FontStyles.Strikethrough;
6233  m_fontStyleStack.Add(FontStyles.Strikethrough);
6234 
6235  if (m_xmlAttribute[1].nameHashCode == 281955 || m_xmlAttribute[1].nameHashCode == 192323)
6236  {
6237  m_strikethroughColor = HexCharsToColor(m_htmlTag, m_xmlAttribute[1].valueStartIndex, m_xmlAttribute[1].valueLength);
6238  m_strikethroughColor.a = m_htmlColor.a < m_strikethroughColor.a ? (byte)(m_htmlColor.a) : (byte)(m_strikethroughColor .a);
6239  }
6240  else
6241  m_strikethroughColor = m_htmlColor;
6242 
6243  m_strikethroughColorStack.Add(m_strikethroughColor);
6244 
6245  return true;
6246  case 444: // </s>
6247  case 412: // </S>
6248  if ((m_fontStyle & FontStyles.Strikethrough) != FontStyles.Strikethrough)
6249  {
6250  if (m_fontStyleStack.Remove(FontStyles.Strikethrough) == 0)
6251  m_style &= ~FontStyles.Strikethrough;
6252  }
6253  return true;
6254  case 117: // <u>
6255  case 85: // <U>
6256  m_style |= FontStyles.Underline;
6257  m_fontStyleStack.Add(FontStyles.Underline);
6258 
6259  if (m_xmlAttribute[1].nameHashCode == 281955 || m_xmlAttribute[1].nameHashCode == 192323)
6260  {
6261  m_underlineColor = HexCharsToColor(m_htmlTag, m_xmlAttribute[1].valueStartIndex, m_xmlAttribute[1].valueLength);
6262  m_underlineColor.a = m_htmlColor.a < m_underlineColor.a ? (byte)(m_htmlColor.a) : (byte)(m_underlineColor.a);
6263  }
6264  else
6265  m_underlineColor = m_htmlColor;
6266 
6267  m_underlineColorStack.Add(m_underlineColor);
6268 
6269  return true;
6270  case 446: // </u>
6271  case 414: // </U>
6272  if ((m_fontStyle & FontStyles.Underline) != FontStyles.Underline)
6273  {
6274  m_underlineColor = m_underlineColorStack.Remove();
6275 
6276  if (m_fontStyleStack.Remove(FontStyles.Underline) == 0)
6277  m_style &= ~FontStyles.Underline;
6278  }
6279  return true;
6280  case 43045: // <mark=#FF00FF80>
6281  case 30245: // <MARK>
6282  m_style |= FontStyles.Highlight;
6283  m_fontStyleStack.Add(FontStyles.Highlight);
6284 
6285  m_highlightColor = HexCharsToColor(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength);
6286  m_highlightColor.a = m_htmlColor.a < m_highlightColor.a ? (byte)(m_htmlColor.a) : (byte)(m_highlightColor.a);
6287  m_highlightColorStack.Add(m_highlightColor);
6288  return true;
6289  case 155892: // </mark>
6290  case 143092: // </MARK>
6291  if ((m_fontStyle & FontStyles.Highlight) != FontStyles.Highlight)
6292  {
6293  m_highlightColor = m_highlightColorStack.Remove();
6294 
6295  if (m_fontStyleStack.Remove(FontStyles.Highlight) == 0)
6296  m_style &= ~FontStyles.Highlight;
6297  }
6298  return true;
6299  case 6552: // <sub>
6300  case 4728: // <SUB>
6301  m_fontScaleMultiplier *= m_currentFontAsset.fontInfo.SubSize > 0 ? m_currentFontAsset.fontInfo.SubSize : 1;
6302  m_baselineOffsetStack.Push(m_baselineOffset);
6303  m_baselineOffset += m_currentFontAsset.fontInfo.SubscriptOffset * m_fontScale * m_fontScaleMultiplier;
6304 
6305  m_fontStyleStack.Add(FontStyles.Subscript);
6306  m_style |= FontStyles.Subscript;
6307  return true;
6308  case 22673: // </sub>
6309  case 20849: // </SUB>
6310  if ((m_style & FontStyles.Subscript) == FontStyles.Subscript)
6311  {
6312  if (m_fontScaleMultiplier < 1)
6313  {
6314  //m_baselineOffset -= m_currentFontAsset.fontInfo.SubscriptOffset * m_fontScale * m_fontScaleMultiplier;
6315  m_baselineOffset = m_baselineOffsetStack.Pop();
6316  m_fontScaleMultiplier /= m_currentFontAsset.fontInfo.SubSize > 0 ? m_currentFontAsset.fontInfo.SubSize : 1;
6317  }
6318 
6319  if (m_fontStyleStack.Remove(FontStyles.Subscript) == 0)
6320  m_style &= ~FontStyles.Subscript;
6321  }
6322  return true;
6323  case 6566: // <sup>
6324  case 4742: // <SUP>
6325  m_fontScaleMultiplier *= m_currentFontAsset.fontInfo.SubSize > 0 ? m_currentFontAsset.fontInfo.SubSize : 1;
6326  m_baselineOffsetStack.Push(m_baselineOffset);
6327  m_baselineOffset += m_currentFontAsset.fontInfo.SuperscriptOffset * m_fontScale * m_fontScaleMultiplier;
6328 
6329  m_fontStyleStack.Add(FontStyles.Superscript);
6330  m_style |= FontStyles.Superscript;
6331  return true;
6332  case 22687: // </sup>
6333  case 20863: // </SUP>
6334  if ((m_style & FontStyles.Superscript) == FontStyles.Superscript)
6335  {
6336  if (m_fontScaleMultiplier < 1)
6337  {
6338  //m_baselineOffset -= m_currentFontAsset.fontInfo.SuperscriptOffset * m_fontScale * m_fontScaleMultiplier;
6339  m_baselineOffset = m_baselineOffsetStack.Pop();
6340  m_fontScaleMultiplier /= m_currentFontAsset.fontInfo.SubSize > 0 ? m_currentFontAsset.fontInfo.SubSize : 1;
6341  }
6342 
6343  if (m_fontStyleStack.Remove(FontStyles.Superscript) == 0)
6344  m_style &= ~FontStyles.Superscript;
6345  }
6346  return true;
6347  case -330774850: // <font-weight>
6348  case 2012149182: // <FONT-WEIGHT>
6349  value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength);
6350  if (value == -9999) return false;
6351 
6352  if ((m_fontStyle & FontStyles.Bold) == FontStyles.Bold)
6353  {
6354  // Nothing happens since Bold is forced on the text.
6355  //m_fontWeight = 700;
6356  return true;
6357  }
6358 
6359 
6360  // Remove bold style
6361  m_style &= ~FontStyles.Bold;
6362 
6363  switch ((int)value)
6364  {
6365  case 100:
6366  m_fontWeightInternal = 100;
6367  break;
6368  case 200:
6369  m_fontWeightInternal = 200;
6370  break;
6371  case 300:
6372  m_fontWeightInternal = 300;
6373  break;
6374  case 400:
6375  m_fontWeightInternal = 400;
6376 
6377  break;
6378  case 500:
6379  m_fontWeightInternal = 500;
6380  break;
6381  case 600:
6382  m_fontWeightInternal = 600;
6383  break;
6384  case 700:
6385  m_fontWeightInternal = 700;
6386  m_style |= FontStyles.Bold;
6387  break;
6388  case 800:
6389  m_fontWeightInternal = 800;
6390  break;
6391  case 900:
6392  m_fontWeightInternal = 900;
6393  break;
6394  }
6395 
6396  m_fontWeightStack.Add(m_fontWeightInternal);
6397 
6398  return true;
6399  case -1885698441: // </font-weight>
6400  case 457225591: // </FONT-WEIGHT>
6401  m_fontWeightInternal = m_fontWeightStack.Remove();
6402  if (m_fontWeightInternal == 400) m_style &= ~FontStyles.Bold;
6403  return true;
6404  case 6380: // <pos=000.00px> <pos=0em> <pos=50%>
6405  case 4556: // <POS>
6406  value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength);
6407  if (value == -9999) return false;
6408 
6409  switch (tagUnits)
6410  {
6411  case TagUnits.Pixels:
6412  //if (m_xmlAttribute[1].nameHashCode == 275917) //
6413  //{
6414  // // left = 3774683
6415  // // right= 136703040
6416  // if (m_xmlAttribute [1].valueHashCode == 136703040)
6417  // {
6418  // // track the endindex so we can return to this character.
6419  // Debug.Log ("align=right startIndex" + endIndex);
6420  // }
6421  //}
6422  m_xAdvance = value;
6423  //m_isIgnoringAlignment = true;
6424  return true;
6425  case TagUnits.FontUnits:
6426  m_xAdvance = value * m_fontScale * m_fontAsset.fontInfo.TabWidth / m_fontAsset.tabSize;
6427  //m_isIgnoringAlignment = true;
6428  return true;
6429  case TagUnits.Percentage:
6430  m_xAdvance = m_marginWidth * value / 100;
6431 
6432  //if (m_xmlAttribute[1].nameHashCode == 275917) //
6433  //{
6434  // //Debug.Log ("align tag.");
6435  // // left = 3774683
6436  // // right= 136703040
6437  // if (m_xmlAttribute [1].valueHashCode == 136703040)
6438  // {
6439  // // track the endindex so we can return to this character.
6440  // SaveWordWrappingState (ref m_SavedAlignment, endIndex, m_characterCount);
6441  // }
6442  //}
6443  //m_isIgnoringAlignment = true;
6444  return true;
6445  }
6446  return false;
6447  case 22501: // </pos>
6448  case 20677: // </POS>
6449  /*
6450  // Should retrun the index of where the tag started and adjust xAdvance.
6451  if (m_isParsingText)
6452  {
6453  if (m_SavedAlignment.previous_WordBreak != 0)
6454  {
6455  float current_xAdvance = m_xAdvance;
6456  endIndex = RestoreWordWrappingState (ref m_SavedAlignment);
6457  m_characterCount -= 1;
6458  m_xAdvance -= current_xAdvance - m_xAdvance;
6459  }
6460  m_SavedAlignment.previous_WordBreak = 0;
6461 
6462  m_isIgnoringAlignment = false;
6463  }
6464  */
6465  m_isIgnoringAlignment = false;
6466  return true;
6467  case 16034505: // <voffset>
6468  case 11642281: // <VOFFSET>
6469  value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength);
6470  if (value == -9999) return false;
6471 
6472  switch (tagUnits)
6473  {
6474  case TagUnits.Pixels:
6475  m_baselineOffset = value;
6476  return true;
6477  case TagUnits.FontUnits:
6478  m_baselineOffset = value * m_fontScale * m_fontAsset.fontInfo.Ascender;
6479  return true;
6480  case TagUnits.Percentage:
6481  //m_baselineOffset = m_marginHeight * val / 100;
6482  return false;
6483  }
6484  return false;
6485  case 54741026: // </voffset>
6486  case 50348802: // </VOFFSET>
6487  m_baselineOffset = 0;
6488  return true;
6489  case 43991: // <page>
6490  case 31191: // <PAGE>
6491  // This tag only works when Overflow - Page mode is used.
6492  if (m_overflowMode == TextOverflowModes.Page)
6493  {
6494  m_xAdvance = 0 + tag_LineIndent + tag_Indent;
6495  m_lineOffset = 0;
6496  m_pageNumber += 1;
6497  m_isNewPage = true;
6498  }
6499  return true;
6500  // <BR> tag is now handled inline where it is replaced by a linefeed or \n.
6501  //case 544: // <BR>
6502  //case 800: // <br>
6503  // m_forceLineBreak = true;
6504  // return true;
6505  case 43969: // <nobr>
6506  case 31169: // <NOBR>
6507  m_isNonBreakingSpace = true;
6508  return true;
6509  case 156816: // </nobr>
6510  case 144016: // </NOBR>
6511  m_isNonBreakingSpace = false;
6512  return true;
6513  case 45545: // <size=>
6514  case 32745: // <SIZE>
6515  value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength);
6516  if (value == -9999) return false;
6517 
6518  switch (tagUnits)
6519  {
6520  case TagUnits.Pixels:
6521  if (m_htmlTag[5] == 43) // <size=+00>
6522  {
6523  m_currentFontSize = m_fontSize + value;
6524  m_sizeStack.Add(m_currentFontSize);
6525  m_fontScale = (m_currentFontSize / m_currentFontAsset.fontInfo.PointSize * m_currentFontAsset.fontInfo.Scale * (m_isOrthographic ? 1 : 0.1f));
6526  return true;
6527  }
6528  else if (m_htmlTag[5] == 45) // <size=-00>
6529  {
6530  m_currentFontSize = m_fontSize + value;
6531  m_sizeStack.Add(m_currentFontSize);
6532  m_fontScale = (m_currentFontSize / m_currentFontAsset.fontInfo.PointSize * m_currentFontAsset.fontInfo.Scale * (m_isOrthographic ? 1 : 0.1f));
6533  return true;
6534  }
6535  else // <size=00.0>
6536  {
6537  m_currentFontSize = value;
6538  m_sizeStack.Add(m_currentFontSize);
6539  m_fontScale = (m_currentFontSize / m_currentFontAsset.fontInfo.PointSize * m_currentFontAsset.fontInfo.Scale * (m_isOrthographic ? 1 : 0.1f));
6540  return true;
6541  }
6542  case TagUnits.FontUnits:
6543  m_currentFontSize = m_fontSize * value;
6544  m_sizeStack.Add(m_currentFontSize);
6545  m_fontScale = (m_currentFontSize / m_currentFontAsset.fontInfo.PointSize * m_currentFontAsset.fontInfo.Scale * (m_isOrthographic ? 1 : 0.1f));
6546  return true;
6547  case TagUnits.Percentage:
6548  m_currentFontSize = m_fontSize * value / 100;
6549  m_sizeStack.Add(m_currentFontSize);
6550  m_fontScale = (m_currentFontSize / m_currentFontAsset.fontInfo.PointSize * m_currentFontAsset.fontInfo.Scale * (m_isOrthographic ? 1 : 0.1f));
6551  return true;
6552  }
6553  return false;
6554  case 158392: // </size>
6555  case 145592: // </SIZE>
6556  m_currentFontSize = m_sizeStack.Remove();
6557  m_fontScale = (m_currentFontSize / m_currentFontAsset.fontInfo.PointSize * m_currentFontAsset.fontInfo.Scale * (m_isOrthographic ? 1 : 0.1f));
6558  return true;
6559  case 41311: // <font=xx>
6560  case 28511: // <FONT>
6561  //Debug.Log("Font name: \"" + new string(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength) + "\" HashCode: " + m_xmlAttribute[0].valueHashCode + " Material Name: \"" + new string(m_htmlTag, m_xmlAttribute[1].valueStartIndex, m_xmlAttribute[1].valueLength) + "\" Hashcode: " + m_xmlAttribute[1].valueHashCode);
6562 
6563  int fontHashCode = m_xmlAttribute[0].valueHashCode;
6564  int materialAttributeHashCode = m_xmlAttribute[1].nameHashCode;
6565  int materialHashCode = m_xmlAttribute[1].valueHashCode;
6566 
6567  // Special handling for <font=default> or <font=Default>
6568  if (fontHashCode == 764638571 || fontHashCode == 523367755)
6569  {
6570  m_currentFontAsset = m_materialReferences[0].fontAsset;
6571  m_currentMaterial = m_materialReferences[0].material;
6572  m_currentMaterialIndex = 0;
6573  //Debug.Log("<font=Default> assigning Font Asset [" + m_currentFontAsset.name + "] with Material [" + m_currentMaterial.name + "].");
6574 
6575  m_fontScale = (m_currentFontSize / m_currentFontAsset.fontInfo.PointSize * m_currentFontAsset.fontInfo.Scale * (m_isOrthographic ? 1 : 0.1f));
6576 
6577  m_materialReferenceStack.Add(m_materialReferences[0]);
6578 
6579  return true;
6580  }
6581 
6582  TMP_FontAsset tempFont;
6583  Material tempMaterial;
6584 
6585  // HANDLE NEW FONT ASSET
6586  if (MaterialReferenceManager.TryGetFontAsset(fontHashCode, out tempFont))
6587  {
6588  //if (tempFont != m_currentFontAsset)
6589  //{
6590  // //Debug.Log("Assigning Font Asset: " + tempFont.name);
6591  // m_currentFontAsset = tempFont;
6592  // m_fontScale = (m_currentFontSize / m_currentFontAsset.fontInfo.PointSize * m_currentFontAsset.fontInfo.Scale * (m_isOrthographic ? 1 : 0.1f));
6593  //}
6594  }
6595  else
6596  {
6597  // Load Font Asset
6598  tempFont = Resources.Load<TMP_FontAsset>(TMP_Settings.defaultFontAssetPath + new string(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength));
6599 
6600  if (tempFont == null)
6601  return false;
6602 
6603  // Add new reference to the font asset as well as default material to the MaterialReferenceManager
6605  }
6606 
6607 
6608  // HANDLE NEW MATERIAL
6609  if (materialAttributeHashCode == 0 && materialHashCode == 0)
6610  {
6611  // No material specified then use default font asset material.
6612  m_currentMaterial = tempFont.material;
6613 
6614  m_currentMaterialIndex = MaterialReference.AddMaterialReference(m_currentMaterial, tempFont, m_materialReferences, m_materialReferenceIndexLookup);
6615 
6616  m_materialReferenceStack.Add(m_materialReferences[m_currentMaterialIndex]);
6617  }
6618  else if (materialAttributeHashCode == 103415287 || materialAttributeHashCode == 72669687) // using material attribute
6619  {
6620  if (MaterialReferenceManager.TryGetMaterial(materialHashCode, out tempMaterial))
6621  {
6622  m_currentMaterial = tempMaterial;
6623 
6624  m_currentMaterialIndex = MaterialReference.AddMaterialReference(m_currentMaterial, tempFont, m_materialReferences, m_materialReferenceIndexLookup);
6625 
6626  m_materialReferenceStack.Add(m_materialReferences[m_currentMaterialIndex]);
6627  }
6628  else
6629  {
6630  // Load new material
6631  tempMaterial = Resources.Load<Material>(TMP_Settings.defaultFontAssetPath + new string(m_htmlTag, m_xmlAttribute[1].valueStartIndex, m_xmlAttribute[1].valueLength));
6632 
6633  if (tempMaterial == null)
6634  return false;
6635 
6636  // Add new reference to this material in the MaterialReferenceManager
6637  MaterialReferenceManager.AddFontMaterial(materialHashCode, tempMaterial);
6638 
6639  m_currentMaterial = tempMaterial;
6640 
6641  m_currentMaterialIndex = MaterialReference.AddMaterialReference(m_currentMaterial, tempFont, m_materialReferences, m_materialReferenceIndexLookup);
6642 
6643  m_materialReferenceStack.Add(m_materialReferences[m_currentMaterialIndex]);
6644  }
6645  }
6646  else
6647  return false;
6648 
6649  m_currentFontAsset = tempFont;
6650  m_fontScale = (m_currentFontSize / m_currentFontAsset.fontInfo.PointSize * m_currentFontAsset.fontInfo.Scale * (m_isOrthographic ? 1 : 0.1f));
6651 
6652  return true;
6653  case 154158: // </font>
6654  case 141358: // </FONT>
6655  {
6656  MaterialReference materialReference = m_materialReferenceStack.Remove();
6657 
6658  m_currentFontAsset = materialReference.fontAsset;
6659  m_currentMaterial = materialReference.material;
6660  m_currentMaterialIndex = materialReference.index;
6661 
6662  m_fontScale = (m_currentFontSize / m_currentFontAsset.fontInfo.PointSize * m_currentFontAsset.fontInfo.Scale * (m_isOrthographic ? 1 : 0.1f));
6663 
6664  return true;
6665  }
6666  case 103415287: // <material="material name">
6667  case 72669687: // <MATERIAL>
6668  materialHashCode = m_xmlAttribute[0].valueHashCode;
6669 
6670  // Special handling for <material=default> or <material=Default>
6671  if (materialHashCode == 764638571 || materialHashCode == 523367755)
6672  {
6673  // Check if material font atlas texture matches that of the current font asset.
6674  //if (m_currentFontAsset.atlas.GetInstanceID() != m_currentMaterial.GetTexture(ShaderUtilities.ID_MainTex).GetInstanceID()) return false;
6675 
6676  m_currentMaterial = m_materialReferences[0].material;
6677  m_currentMaterialIndex = 0;
6678 
6679  m_materialReferenceStack.Add(m_materialReferences[0]);
6680 
6681  return true;
6682  }
6683 
6684 
6685  // Check if material
6686  if (MaterialReferenceManager.TryGetMaterial(materialHashCode, out tempMaterial))
6687  {
6688  // Check if material font atlas texture matches that of the current font asset.
6689  //if (m_currentFontAsset.atlas.GetInstanceID() != tempMaterial.GetTexture(ShaderUtilities.ID_MainTex).GetInstanceID()) return false;
6690 
6691  m_currentMaterial = tempMaterial;
6692 
6693  m_currentMaterialIndex = MaterialReference.AddMaterialReference(m_currentMaterial, m_currentFontAsset, m_materialReferences, m_materialReferenceIndexLookup);
6694 
6695  m_materialReferenceStack.Add(m_materialReferences[m_currentMaterialIndex]);
6696  }
6697  else
6698  {
6699  // Load new material
6700  tempMaterial = Resources.Load<Material>(TMP_Settings.defaultFontAssetPath + new string(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength));
6701 
6702  if (tempMaterial == null)
6703  return false;
6704 
6705  // Check if material font atlas texture matches that of the current font asset.
6706  //if (m_currentFontAsset.atlas.GetInstanceID() != tempMaterial.GetTexture(ShaderUtilities.ID_MainTex).GetInstanceID()) return false;
6707 
6708  // Add new reference to this material in the MaterialReferenceManager
6709  MaterialReferenceManager.AddFontMaterial(materialHashCode, tempMaterial);
6710 
6711  m_currentMaterial = tempMaterial;
6712 
6713  m_currentMaterialIndex = MaterialReference.AddMaterialReference(m_currentMaterial, m_currentFontAsset , m_materialReferences, m_materialReferenceIndexLookup);
6714 
6715  m_materialReferenceStack.Add(m_materialReferences[m_currentMaterialIndex]);
6716  }
6717  return true;
6718  case 374360934: // </material>
6719  case 343615334: // </MATERIAL>
6720  {
6721  //if (m_currentMaterial.GetTexture(ShaderUtilities.ID_MainTex).GetInstanceID() != m_materialReferenceStack.PreviousItem().material.GetTexture(ShaderUtilities.ID_MainTex).GetInstanceID())
6722  // return false;
6723 
6724  MaterialReference materialReference = m_materialReferenceStack.Remove();
6725 
6726  m_currentMaterial = materialReference.material;
6727  m_currentMaterialIndex = materialReference.index;
6728 
6729  return true;
6730  }
6731  case 320078: // <space=000.00>
6732  case 230446: // <SPACE>
6733  value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength);
6734  if (value == -9999) return false;
6735 
6736  switch (tagUnits)
6737  {
6738  case TagUnits.Pixels:
6739  m_xAdvance += value;
6740  return true;
6741  case TagUnits.FontUnits:
6742  m_xAdvance += value * m_fontScale * m_fontAsset.fontInfo.TabWidth / m_fontAsset.tabSize;
6743  return true;
6744  case TagUnits.Percentage:
6745  // Not applicable
6746  return false;
6747  }
6748  return false;
6749  case 276254: // <alpha=#FF>
6750  case 186622: // <ALPHA>
6751  if (m_xmlAttribute[0].valueLength != 3) return false;
6752 
6753  m_htmlColor.a = (byte)(HexToInt(m_htmlTag[7]) * 16 + HexToInt(m_htmlTag[8]));
6754  return true;
6755 
6756  case 1750458: // <a name=" ">
6757  return false;
6758  case 426: // </a>
6759  return true;
6760  case 43066: // <link="name">
6761  case 30266: // <LINK>
6762  if (m_isParsingText && !m_isCalculatingPreferredValues)
6763  {
6764  int index = m_textInfo.linkCount;
6765 
6766  if (index + 1 > m_textInfo.linkInfo.Length)
6767  TMP_TextInfo.Resize(ref m_textInfo.linkInfo, index + 1);
6768 
6769  m_textInfo.linkInfo[index].textComponent = this;
6770  m_textInfo.linkInfo[index].hashCode = m_xmlAttribute[0].valueHashCode;
6771  m_textInfo.linkInfo[index].linkTextfirstCharacterIndex = m_characterCount;
6772 
6773  m_textInfo.linkInfo[index].linkIdFirstCharacterIndex = startIndex + m_xmlAttribute[0].valueStartIndex;
6774  m_textInfo.linkInfo[index].linkIdLength = m_xmlAttribute[0].valueLength;
6775  m_textInfo.linkInfo[index].SetLinkID(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength);
6776  }
6777  return true;
6778  case 155913: // </link>
6779  case 143113: // </LINK>
6780  if (m_isParsingText && !m_isCalculatingPreferredValues)
6781  {
6782  if (m_textInfo.linkCount < m_textInfo.linkInfo.Length)
6783  {
6784  m_textInfo.linkInfo[m_textInfo.linkCount].linkTextLength = m_characterCount - m_textInfo.linkInfo[m_textInfo.linkCount].linkTextfirstCharacterIndex;
6785 
6786  m_textInfo.linkCount += 1;
6787  }
6788  }
6789  return true;
6790  case 275917: // <align=>
6791  case 186285: // <ALIGN>
6792  switch (m_xmlAttribute[0].valueHashCode)
6793  {
6794  case 3774683: // <align=left>
6795  m_lineJustification = TextAlignmentOptions.Left;
6796  m_lineJustificationStack.Add(m_lineJustification);
6797  return true;
6798  case 136703040: // <align=right>
6799  m_lineJustification = TextAlignmentOptions.Right;
6800  m_lineJustificationStack.Add(m_lineJustification);
6801  return true;
6802  case -458210101: // <align=center>
6803  m_lineJustification = TextAlignmentOptions.Center;
6804  m_lineJustificationStack.Add(m_lineJustification);
6805  return true;
6806  case -523808257: // <align=justified>
6807  m_lineJustification = TextAlignmentOptions.Justified;
6808  m_lineJustificationStack.Add(m_lineJustification);
6809  return true;
6810  case 122383428: // <align=flush>
6811  m_lineJustification = TextAlignmentOptions.Flush;
6812  m_lineJustificationStack.Add(m_lineJustification);
6813  return true;
6814  }
6815  return false;
6816  case 1065846: // </align>
6817  case 976214: // </ALIGN>
6818  m_lineJustification = m_lineJustificationStack.Remove();
6819  return true;
6820  case 327550: // <width=xx>
6821  case 237918: // <WIDTH>
6822  value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength);
6823  if (value == -9999) return false;
6824 
6825  switch (tagUnits)
6826  {
6827  case TagUnits.Pixels:
6828  m_width = value;
6829  break;
6830  case TagUnits.FontUnits:
6831  return false;
6832  //break;
6833  case TagUnits.Percentage:
6834  m_width = m_marginWidth * value / 100;
6835  break;
6836  }
6837  return true;
6838  case 1117479: // </width>
6839  case 1027847: // </WIDTH>
6840  m_width = -1;
6841  return true;
6842  // STYLE tag is now handled inline and replaced by its definition.
6843  //case 322689: // <style="name">
6844  //case 233057: // <STYLE>
6845  // TMP_Style style = TMP_StyleSheet.GetStyle(m_xmlAttribute[0].valueHashCode);
6846 
6847  // if (style == null) return false;
6848 
6849  // m_styleStack.Add(style.hashCode);
6850 
6851  // // Parse Style Macro
6852  // for (int i = 0; i < style.styleOpeningTagArray.Length; i++)
6853  // {
6854  // if (style.styleOpeningTagArray[i] == 60)
6855  // {
6856  // if (ValidateHtmlTag(style.styleOpeningTagArray, i + 1, out i) == false) return false;
6857  // }
6858  // }
6859  // return true;
6860  //case 1112618: // </style>
6861  //case 1022986: // </STYLE>
6862  // style = TMP_StyleSheet.GetStyle(m_xmlAttribute[0].valueHashCode);
6863 
6864  // if (style == null)
6865  // {
6866  // // Get style from the Style Stack
6867  // int styleHashCode = m_styleStack.CurrentItem();
6868  // style = TMP_StyleSheet.GetStyle(styleHashCode);
6869 
6870  // m_styleStack.Remove();
6871  // }
6872 
6873  // if (style == null) return false;
6874  // //// Parse Style Macro
6875  // for (int i = 0; i < style.styleClosingTagArray.Length; i++)
6876  // {
6877  // if (style.styleClosingTagArray[i] == 60)
6878  // ValidateHtmlTag(style.styleClosingTagArray, i + 1, out i);
6879  // }
6880  // return true;
6881  case 281955: // <color> <color=#FF00FF> or <color=#FF00FF00>
6882  case 192323: // <COLOR=#FF00FF>
6883  // <color=#FFF> 3 Hex (short hand)
6884  if (m_htmlTag[6] == 35 && tagCharCount == 10)
6885  {
6886  m_htmlColor = HexCharsToColor(m_htmlTag, tagCharCount);
6887  m_colorStack.Add(m_htmlColor);
6888  return true;
6889  }
6890  // <color=#FFF7> 4 Hex (short hand)
6891  else if (m_htmlTag[6] == 35 && tagCharCount == 11)
6892  {
6893  m_htmlColor = HexCharsToColor(m_htmlTag, tagCharCount);
6894  m_colorStack.Add(m_htmlColor);
6895  return true;
6896  }
6897  // <color=#FF00FF> 3 Hex pairs
6898  if (m_htmlTag[6] == 35 && tagCharCount == 13)
6899  {
6900  m_htmlColor = HexCharsToColor(m_htmlTag, tagCharCount);
6901  m_colorStack.Add(m_htmlColor);
6902  return true;
6903  }
6904  // <color=#FF00FF00> 4 Hex pairs
6905  else if (m_htmlTag[6] == 35 && tagCharCount == 15)
6906  {
6907  m_htmlColor = HexCharsToColor(m_htmlTag, tagCharCount);
6908  m_colorStack.Add(m_htmlColor);
6909  return true;
6910  }
6911 
6912  // <color=name>
6913  switch (m_xmlAttribute[0].valueHashCode)
6914  {
6915  case 125395: // <color=red>
6916  m_htmlColor = Color.red;
6917  m_colorStack.Add(m_htmlColor);
6918  return true;
6919  case 3573310: // <color=blue>
6920  m_htmlColor = Color.blue;
6921  m_colorStack.Add(m_htmlColor);
6922  return true;
6923  case 117905991: // <color=black>
6924  m_htmlColor = Color.black;
6925  m_colorStack.Add(m_htmlColor);
6926  return true;
6927  case 121463835: // <color=green>
6928  m_htmlColor = Color.green;
6929  m_colorStack.Add(m_htmlColor);
6930  return true;
6931  case 140357351: // <color=white>
6932  m_htmlColor = Color.white;
6933  m_colorStack.Add(m_htmlColor);
6934  return true;
6935  case 26556144: // <color=orange>
6936  m_htmlColor = new Color32(255, 128, 0, 255);
6937  m_colorStack.Add(m_htmlColor);
6938  return true;
6939  case -36881330: // <color=purple>
6940  m_htmlColor = new Color32(160, 32, 240, 255);
6941  m_colorStack.Add(m_htmlColor);
6942  return true;
6943  case 554054276: // <color=yellow>
6944  m_htmlColor = Color.yellow;
6945  m_colorStack.Add(m_htmlColor);
6946  return true;
6947  }
6948  return false;
6949 
6950  case 100149144: //<gradient>
6951  case 69403544: // <GRADIENT>
6952  int gradientPresetHashCode = m_xmlAttribute[0].valueHashCode;
6953  TMP_ColorGradient tempColorGradientPreset;
6954 
6955  // Check if Color Gradient Preset has already been loaded.
6956  if (MaterialReferenceManager.TryGetColorGradientPreset(gradientPresetHashCode, out tempColorGradientPreset))
6957  {
6958  m_colorGradientPreset = tempColorGradientPreset;
6959  }
6960  else
6961  {
6962  // Load Color Gradient Preset
6963  if (tempColorGradientPreset == null)
6964  {
6965  tempColorGradientPreset = Resources.Load<TMP_ColorGradient>(TMP_Settings.defaultColorGradientPresetsPath + new string(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength));
6966  }
6967 
6968  if (tempColorGradientPreset == null)
6969  return false;
6970 
6971  MaterialReferenceManager.AddColorGradientPreset(gradientPresetHashCode, tempColorGradientPreset);
6972  m_colorGradientPreset = tempColorGradientPreset;
6973  }
6974 
6975  m_colorGradientStack.Add(m_colorGradientPreset);
6976 
6977  // TODO : Add support for defining preset in the tag itself
6978 
6979  return true;
6980 
6981  case 371094791: // </gradient>
6982  case 340349191: // </GRADIENT>
6983  m_colorGradientPreset = m_colorGradientStack.Remove();
6984  return true;
6985 
6986  case 1983971: // <cspace=xx.x>
6987  case 1356515: // <CSPACE>
6988  value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength);
6989  if (value == -9999) return false;
6990 
6991  switch (tagUnits)
6992  {
6993  case TagUnits.Pixels:
6994  m_cSpacing = value;
6995  break;
6996  case TagUnits.FontUnits:
6997  m_cSpacing = value;
6998  m_cSpacing *= m_fontScale * m_fontAsset.fontInfo.TabWidth / m_fontAsset.tabSize;
6999  break;
7000  case TagUnits.Percentage:
7001  return false;
7002  }
7003  return true;
7004  case 7513474: // </cspace>
7005  case 6886018: // </CSPACE>
7006  if (!m_isParsingText) return true;
7007 
7008  // Adjust xAdvance to remove extra space from last character.
7009  if (m_characterCount > 0)
7010  {
7011  m_xAdvance -= m_cSpacing;
7012  m_textInfo.characterInfo[m_characterCount - 1].xAdvance = m_xAdvance;
7013  }
7014  m_cSpacing = 0;
7015  return true;
7016  case 2152041: // <mspace=xx.x>
7017  case 1524585: // <MSPACE>
7018  value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength);
7019  if (value == -9999) return false;
7020 
7021  switch (tagUnits)
7022  {
7023  case TagUnits.Pixels:
7024  m_monoSpacing = value;
7025  break;
7026  case TagUnits.FontUnits:
7027  m_monoSpacing = value;
7028  m_monoSpacing *= m_fontScale * m_fontAsset.fontInfo.TabWidth / m_fontAsset.tabSize;
7029  break;
7030  case TagUnits.Percentage:
7031  return false;
7032  }
7033  return true;
7034  case 7681544: // </mspace>
7035  case 7054088: // </MSPACE>
7036  m_monoSpacing = 0;
7037  return true;
7038  case 280416: // <class="name">
7039  return false;
7040  case 1071884: // </color>
7041  case 982252: // </COLOR>
7042  m_htmlColor = m_colorStack.Remove();
7043  return true;
7044  case 2068980: // <indent=10px> <indent=10em> <indent=50%>
7045  case 1441524: // <INDENT>
7046  value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength);
7047  if (value == -9999) return false;
7048 
7049  switch (tagUnits)
7050  {
7051  case TagUnits.Pixels:
7052  tag_Indent = value;
7053  break;
7054  case TagUnits.FontUnits:
7055  tag_Indent = value;
7056  tag_Indent *= m_fontScale * m_fontAsset.fontInfo.TabWidth / m_fontAsset.tabSize;
7057  break;
7058  case TagUnits.Percentage:
7059  tag_Indent = m_marginWidth * value / 100;
7060  break;
7061  }
7062  m_indentStack.Add(tag_Indent);
7063 
7064  m_xAdvance = tag_Indent;
7065  return true;
7066  case 7598483: // </indent>
7067  case 6971027: // </INDENT>
7068  tag_Indent = m_indentStack.Remove();
7069  //m_xAdvance = tag_Indent;
7070  return true;
7071  case 1109386397: // <line-indent>
7072  case -842656867: // <LINE-INDENT>
7073  value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength);
7074  if (value == -9999) return false;
7075 
7076  switch (tagUnits)
7077  {
7078  case TagUnits.Pixels:
7079  tag_LineIndent = value;
7080  break;
7081  case TagUnits.FontUnits:
7082  tag_LineIndent = value;
7083  tag_LineIndent *= m_fontScale * m_fontAsset.fontInfo.TabWidth / m_fontAsset.tabSize;
7084  break;
7085  case TagUnits.Percentage:
7086  tag_LineIndent = m_marginWidth * value / 100;
7087  break;
7088  }
7089 
7090  m_xAdvance += tag_LineIndent;
7091  return true;
7092  case -445537194: // </line-indent>
7093  case 1897386838: // </LINE-INDENT>
7094  tag_LineIndent = 0;
7095  return true;
7096  case 2246877: // <sprite=x>
7097  case 1619421: // <SPRITE>
7098  int spriteAssetHashCode = m_xmlAttribute[0].valueHashCode;
7099  TMP_SpriteAsset tempSpriteAsset;
7100  m_spriteIndex = -1;
7101 
7102  // CHECK TAG FORMAT
7103  if (m_xmlAttribute[0].valueType == TagType.None || m_xmlAttribute[0].valueType == TagType.NumericalValue)
7104  {
7105  // No Sprite Asset is assigned to the text object
7106  if (m_spriteAsset != null)
7107  {
7108  m_currentSpriteAsset = m_spriteAsset;
7109  }
7110  else if (m_defaultSpriteAsset != null)
7111  {
7112  m_currentSpriteAsset = m_defaultSpriteAsset;
7113  }
7114  else if (m_defaultSpriteAsset == null)
7115  {
7116  if (TMP_Settings.defaultSpriteAsset != null)
7117  m_defaultSpriteAsset = TMP_Settings.defaultSpriteAsset;
7118  else
7119  m_defaultSpriteAsset = Resources.Load<TMP_SpriteAsset>("Sprite Assets/Default Sprite Asset");
7120 
7121  m_currentSpriteAsset = m_defaultSpriteAsset;
7122  }
7123 
7124  // No valid sprite asset available
7125  if (m_currentSpriteAsset == null)
7126  return false;
7127  }
7128  else
7129  {
7130  // A Sprite Asset has been specified
7131  if (MaterialReferenceManager.TryGetSpriteAsset(spriteAssetHashCode, out tempSpriteAsset))
7132  {
7133  m_currentSpriteAsset = tempSpriteAsset;
7134  }
7135  else
7136  {
7137  // Load Sprite Asset
7138  if (tempSpriteAsset == null)
7139  {
7140  tempSpriteAsset = Resources.Load<TMP_SpriteAsset>(TMP_Settings.defaultSpriteAssetPath + new string(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength));
7141  }
7142 
7143  if (tempSpriteAsset == null)
7144  return false;
7145 
7146  //Debug.Log("Loading & assigning new Sprite Asset: " + tempSpriteAsset.name);
7147  MaterialReferenceManager.AddSpriteAsset(spriteAssetHashCode, tempSpriteAsset);
7148  m_currentSpriteAsset = tempSpriteAsset;
7149  }
7150  }
7151 
7152  // Handling of <sprite=index> legacy tag format.
7153  if (m_xmlAttribute[0].valueType == TagType.NumericalValue) // <sprite=index>
7154  {
7155  int index = (int)ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength);
7156  if (index == -9999) return false;
7157 
7158  // Check to make sure sprite index is valid
7159  if (index > m_currentSpriteAsset.spriteInfoList.Count - 1) return false;
7160 
7161  m_spriteIndex = index;
7162  }
7163 
7164  m_spriteColor = s_colorWhite;
7165  m_tintSprite = false;
7166 
7167  // Handle Sprite Tag Attributes
7168  for (int i = 0; i < m_xmlAttribute.Length && m_xmlAttribute[i].nameHashCode != 0; i++)
7169  {
7170  //Debug.Log("Attribute[" + i + "].nameHashCode=" + m_xmlAttribute[i].nameHashCode + " Value:" + ConvertToFloat(m_htmlTag, m_xmlAttribute[i].valueStartIndex, m_xmlAttribute[i].valueLength));
7171  int nameHashCode = m_xmlAttribute[i].nameHashCode;
7172  int index = 0;
7173 
7174  switch (nameHashCode)
7175  {
7176  case 43347: // <sprite name="">
7177  case 30547: // <SPRITE NAME="">
7178  m_currentSpriteAsset = TMP_SpriteAsset.SearchForSpriteByHashCode(m_currentSpriteAsset, m_xmlAttribute[i].valueHashCode, true, out index);
7179  if (index == -1) return false;
7180 
7181  m_spriteIndex = index;
7182  break;
7183  case 295562: // <sprite index=>
7184  case 205930: // <SPRITE INDEX=>
7185  index = (int)ConvertToFloat(m_htmlTag, m_xmlAttribute[1].valueStartIndex, m_xmlAttribute[1].valueLength);
7186  if (index == -9999) return false;
7187 
7188  // Check to make sure sprite index is valid
7189  if (index > m_currentSpriteAsset.spriteInfoList.Count - 1) return false;
7190 
7191  m_spriteIndex = index;
7192  break;
7193  case 45819: // tint
7194  case 33019: // TINT
7195  m_tintSprite = ConvertToFloat(m_htmlTag, m_xmlAttribute[i].valueStartIndex, m_xmlAttribute[i].valueLength) != 0;
7196  break;
7197  case 281955: // color=#FF00FF80
7198  case 192323: // COLOR
7199  m_spriteColor = HexCharsToColor(m_htmlTag, m_xmlAttribute[i].valueStartIndex, m_xmlAttribute[i].valueLength);
7200  break;
7201  case 39505: // anim="0,16,12" start, end, fps
7202  case 26705: // ANIM
7203  //Debug.Log("Start: " + m_xmlAttribute[i].valueStartIndex + " Length: " + m_xmlAttribute[i].valueLength);
7204  int paramCount = GetAttributeParameters(m_htmlTag, m_xmlAttribute[i].valueStartIndex, m_xmlAttribute[i].valueLength, ref m_attributeParameterValues);
7205  if (paramCount != 3) return false;
7206 
7207  m_spriteIndex = (int)m_attributeParameterValues[0];
7208 
7209  if (m_isParsingText)
7210  {
7211  // TODO : fix this!
7212  //if (m_attributeParameterValues[0] > m_currentSpriteAsset.spriteInfoList.Count - 1 || m_attributeParameterValues[1] > m_currentSpriteAsset.spriteInfoList.Count - 1)
7213  // return false;
7214 
7215  spriteAnimator.DoSpriteAnimation(m_characterCount, m_currentSpriteAsset, m_spriteIndex, (int)m_attributeParameterValues[1], (int)m_attributeParameterValues[2]);
7216  }
7217 
7218  break;
7219  //case 45545: // size
7220  //case 32745: // SIZE
7221 
7222  // break;
7223  default:
7224  if (nameHashCode != 2246877 && nameHashCode != 1619421)
7225  return false;
7226  break;
7227  }
7228  }
7229 
7230  if (m_spriteIndex == -1) return false;
7231 
7232  // Material HashCode for the Sprite Asset is the Sprite Asset Hash Code
7233  m_currentMaterialIndex = MaterialReference.AddMaterialReference(m_currentSpriteAsset.material, m_currentSpriteAsset, m_materialReferences, m_materialReferenceIndexLookup);
7234 
7235  m_textElementType = TMP_TextElementType.Sprite;
7236  return true;
7237  case 730022849: // <lowercase>
7238  case 514803617: // <LOWERCASE>
7239  m_style |= FontStyles.LowerCase;
7240  m_fontStyleStack.Add(FontStyles.LowerCase);
7241  return true;
7242  case -1668324918: // </lowercase>
7243  case -1883544150: // </LOWERCASE>
7244  if (m_fontStyleStack.Remove(FontStyles.LowerCase) == 0)
7245  m_style &= ~FontStyles.LowerCase;
7246  return true;
7247  case 13526026: // <allcaps>
7248  case 9133802: // <ALLCAPS>
7249  case 781906058: // <uppercase>
7250  case 566686826: // <UPPERCASE>
7251  m_style |= FontStyles.UpperCase;
7252  m_fontStyleStack.Add(FontStyles.UpperCase);
7253  return true;
7254  case 52232547: // </allcaps>
7255  case 47840323: // </ALLCAPS>
7256  case -1616441709: // </uppercase>
7257  case -1831660941: // </UPPERCASE>
7258  if (m_fontStyleStack.Remove(FontStyles.UpperCase) == 0)
7259  m_style &= ~FontStyles.UpperCase;
7260  return true;
7261  case 766244328: // <smallcaps>
7262  case 551025096: // <SMALLCAPS>
7263  m_style |= FontStyles.SmallCaps;
7264  m_fontStyleStack.Add(FontStyles.SmallCaps);
7265  return true;
7266  case -1632103439: // </smallcaps>
7267  case -1847322671: // </SMALLCAPS>
7268  if (m_fontStyleStack.Remove(FontStyles.SmallCaps) == 0)
7269  m_style &= ~FontStyles.SmallCaps;
7270  return true;
7271  case 2109854: // <margin=00.0> <margin=00em> <margin=50%>
7272  case 1482398: // <MARGIN>
7273  value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength); // px
7274  if (value == -9999) return false;
7275 
7276  m_marginLeft = value;
7277  switch (tagUnits)
7278  {
7279  case TagUnits.Pixels:
7280  // Default behavior
7281  break;
7282  case TagUnits.FontUnits:
7283  m_marginLeft *= m_fontScale * m_fontAsset.fontInfo.TabWidth / m_fontAsset.tabSize;
7284  break;
7285  case TagUnits.Percentage:
7286  m_marginLeft = (m_marginWidth - (m_width != -1 ? m_width : 0)) * m_marginLeft / 100;
7287  break;
7288  }
7289  m_marginLeft = m_marginLeft >= 0 ? m_marginLeft : 0;
7290  m_marginRight = m_marginLeft;
7291 
7292  return true;
7293  case 7639357: // </margin>
7294  case 7011901: // </MARGIN>
7295  m_marginLeft = 0;
7296  m_marginRight = 0;
7297  return true;
7298  case 1100728678: // <margin-left=xx.x>
7299  case -855002522: // <MARGIN-LEFT>
7300  value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength); // px
7301  if (value == -9999) return false;
7302 
7303  m_marginLeft = value;
7304  switch (tagUnits)
7305  {
7306  case TagUnits.Pixels:
7307  // Default behavior
7308  break;
7309  case TagUnits.FontUnits:
7310  m_marginLeft *= m_fontScale * m_fontAsset.fontInfo.TabWidth / m_fontAsset.tabSize;
7311  break;
7312  case TagUnits.Percentage:
7313  m_marginLeft = (m_marginWidth - (m_width != -1 ? m_width : 0)) * m_marginLeft / 100;
7314  break;
7315  }
7316  m_marginLeft = m_marginLeft >= 0 ? m_marginLeft : 0;
7317  return true;
7318  case -884817987: // <margin-right=xx.x>
7319  case -1690034531: // <MARGIN-RIGHT>
7320  value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength); // px
7321  if (value == -9999) return false;
7322 
7323  m_marginRight = value;
7324  switch (tagUnits)
7325  {
7326  case TagUnits.Pixels:
7327  // Default behavior
7328  break;
7329  case TagUnits.FontUnits:
7330  m_marginRight *= m_fontScale * m_fontAsset.fontInfo.TabWidth / m_fontAsset.tabSize;
7331  break;
7332  case TagUnits.Percentage:
7333  m_marginRight = (m_marginWidth - (m_width != -1 ? m_width : 0)) * m_marginRight / 100;
7334  break;
7335  }
7336  m_marginRight = m_marginRight >= 0 ? m_marginRight : 0;
7337  return true;
7338  case 1109349752: // <line-height=xx.x>
7339  case -842693512: // <LINE-HEIGHT>
7340  value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength);
7341  if (value == -9999 || value == 0) return false;
7342 
7343  m_lineHeight = value;
7344  switch (tagUnits)
7345  {
7346  case TagUnits.Pixels:
7347  //m_lineHeight = value;
7348  break;
7349  case TagUnits.FontUnits:
7350  m_lineHeight *= m_fontAsset.fontInfo.LineHeight * m_fontScale;
7351  break;
7352  case TagUnits.Percentage:
7353  m_lineHeight = m_fontAsset.fontInfo.LineHeight * m_lineHeight / 100 * m_fontScale;
7354  break;
7355  }
7356  return true;
7357  case -445573839: // </line-height>
7358  case 1897350193: // </LINE-HEIGHT>
7359  m_lineHeight = TMP_Math.FLOAT_UNSET;
7360  return true;
7361  case 15115642: // <noparse>
7362  case 10723418: // <NOPARSE>
7363  tag_NoParsing = true;
7364  return true;
7365  case 1913798: // <action>
7366  case 1286342: // <ACTION>
7367  int actionID = m_xmlAttribute[0].valueHashCode;
7368 
7369  if (m_isParsingText)
7370  {
7371  m_actionStack.Add(actionID);
7372 
7373  Debug.Log("Action ID: [" + actionID + "] First character index: " + m_characterCount);
7374 
7375 
7376  }
7377  //if (m_isParsingText)
7378  //{
7379  // TMP_Action action = TMP_Action.GetAction(m_xmlAttribute[0].valueHashCode);
7380  //}
7381  return true;
7382  case 7443301: // </action>
7383  case 6815845: // </ACTION>
7384  if (m_isParsingText)
7385  {
7386  Debug.Log("Action ID: [" + m_actionStack.CurrentItem() + "] Last character index: " + (m_characterCount - 1));
7387  }
7388 
7389  m_actionStack.Remove();
7390  return true;
7391  case 315682: // <scale=xx.x>
7392  case 226050: // <SCALE=xx.x>
7393  value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength);
7394  if (value == -9999) return false;
7395 
7396  m_FXMatrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(value, 1, 1));
7397  m_isFXMatrixSet = true;
7398 
7399  return true;
7400  case 1105611: // </scale>
7401  case 1015979: // </SCALE>
7402  m_isFXMatrixSet = false;
7403  return true;
7404  case 2227963: // <rotate=xx.x>
7405  case 1600507: // <ROTATE=xx.x>
7406  // TODO: Add ability to use Random Rotation
7407 
7408  value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength);
7409  if (value == -9999) return false;
7410 
7411  m_FXMatrix = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0, 0, value), Vector3.one);
7412  m_isFXMatrixSet = true;
7413 
7414  return true;
7415  case 7757466: // </rotate>
7416  case 7130010: // </ROTATE>
7417  m_isFXMatrixSet = false;
7418  return true;
7419  case 317446: // <table>
7420  case 227814: // <TABLE>
7421  switch (m_xmlAttribute[1].nameHashCode)
7422  {
7423  case 327550: // width
7424  float tableWidth = ConvertToFloat(m_htmlTag, m_xmlAttribute[1].valueStartIndex, m_xmlAttribute[1].valueLength);
7425 
7426  switch (tagUnits)
7427  {
7428  case TagUnits.Pixels:
7429  Debug.Log("Table width = " + tableWidth + "px.");
7430  break;
7431  case TagUnits.FontUnits:
7432  Debug.Log("Table width = " + tableWidth + "em.");
7433  break;
7434  case TagUnits.Percentage:
7435  Debug.Log("Table width = " + tableWidth + "%.");
7436  break;
7437  }
7438  break;
7439  }
7440  return true;
7441  case 1107375: // </table>
7442  case 1017743: // </TABLE>
7443  return true;
7444  case 926: // <tr>
7445  case 670: // <TR>
7446  return true;
7447  case 3229: // </tr>
7448  case 2973: // </TR>
7449  return true;
7450  case 916: // <th>
7451  case 660: // <TH>
7452  // Set style to bold and center alignment
7453  return true;
7454  case 3219: // </th>
7455  case 2963: // </TH>
7456  return true;
7457  case 912: // <td>
7458  case 656: // <TD>
7459  // Style options
7460  for (int i = 1; i < m_xmlAttribute.Length && m_xmlAttribute[i].nameHashCode != 0; i++)
7461  {
7462  switch (m_xmlAttribute[i].nameHashCode)
7463  {
7464  case 327550: // width
7465  float tableWidth = ConvertToFloat(m_htmlTag, m_xmlAttribute[i].valueStartIndex, m_xmlAttribute[i].valueLength);
7466 
7467  switch (tagUnits)
7468  {
7469  case TagUnits.Pixels:
7470  Debug.Log("Table width = " + tableWidth + "px.");
7471  break;
7472  case TagUnits.FontUnits:
7473  Debug.Log("Table width = " + tableWidth + "em.");
7474  break;
7475  case TagUnits.Percentage:
7476  Debug.Log("Table width = " + tableWidth + "%.");
7477  break;
7478  }
7479  break;
7480  case 275917: // align
7481  switch (m_xmlAttribute[i].valueHashCode)
7482  {
7483  case 3774683: // left
7484  Debug.Log("TD align=\"left\".");
7485  break;
7486  case 136703040: // right
7487  Debug.Log("TD align=\"right\".");
7488  break;
7489  case -458210101: // center
7490  Debug.Log("TD align=\"center\".");
7491  break;
7492  case -523808257: // justified
7493  Debug.Log("TD align=\"justified\".");
7494  break;
7495  }
7496  break;
7497  }
7498  }
7499 
7500  return true;
7501  case 3215: // </td>
7502  case 2959: // </TD>
7503  return true;
7504  }
7505  }
7506  return false;
7507  }
7508  }
7509 }
static bool enableKerning
Controls if Kerning is enabled on newly created text objects by default.
Definition: TMP_Settings.cs:38
Positional adjustments of a glyph
VertexSortingOrder geometrySortingOrder
Determines the sorting order of the geometry of the text object.
Definition: TMP_Text.cs:916
T Remove()
Function to retrieve an item from the stack.
virtual int SetArraySizes(int[] chars)
Method used to determine the number of visible characters and required buffer allocations.
Definition: TMP_Text.cs:3398
Vector2 GetPreferredValues()
Function to Calculate the Preferred Width and Height of the text object.
Definition: TMP_Text.cs:3411
virtual float preferredHeight
Computed preferred height of the text object.
Definition: TMP_Text.cs:1275
Vector2 GetRenderedValues()
Method returning the rendered width and height of the text object.
Definition: TMP_Text.cs:3620
bool isLinkedTextComponent
Indicates whether this text component is linked to another.
Definition: TMP_Text.cs:717
TextRenderFlags
Flags controlling what vertex data gets pushed to the mesh.
Definition: TMP_Text.cs:88
virtual void SetSharedMaterials(Material[] materials)
Definition: TMP_Text.cs:1444
Structure used to track XML tags of various types.
override void CrossFadeAlpha(float alpha, float duration, bool ignoreTimeScale)
Tweens the alpha of the CanvasRenderer color associated with this Graphic.
Definition: TMP_Text.cs:1650
virtual void SetFontBaseMaterial(Material mat)
Function called internally when assigning a new base material.
Definition: TMP_Text.cs:1433
float mappingUvLineOffset
Controls the UV Offset for the various texture mapping mode on the text object.
Definition: TMP_Text.cs:893
bool isUsingLegacyAnimationComponent
Property to handle legacy animation component.
Definition: TMP_Text.cs:1036
virtual void UpdateGeometry(Mesh mesh, int index)
Function to force the regeneration of the text object.
Definition: TMP_Text.cs:1596
float alpha
Sets the vertex color alpha value.
Definition: TMP_Text.cs:247
static string defaultFontAssetPath
The relative path to a Resources folder in the project.
virtual Bounds GetCompoundBounds()
Method returning the compound bounds of the text object and child sub objects.
Definition: TMP_Text.cs:4424
int maxVisibleLines
Allows control over how many lines of text are displayed.
Definition: TMP_Text.cs:962
float fontSize
The point size of the font.
Definition: TMP_Text.cs:390
virtual void SaveGlyphVertexInfo(float padding, float style_padding, Color32 vertexColor)
Store vertex information for each character.
Definition: TMP_Text.cs:4763
virtual Material [] GetMaterials(Material[] mats)
Method returning instances of the materials used by the text object.
Definition: TMP_Text.cs:1450
void SetText(string text, float arg0, float arg1)
Definition: TMP_Text.cs:1765
bool ReplaceOpeningStyleTag(ref StringBuilder sourceText, int srcIndex, out int srcOffset, ref int[] charBuffer, ref int writeIndex)
Method to handle inline replacement of style tag by opening style definition.
Definition: TMP_Text.cs:2790
Structure which contains information about the individual lines of text.
Definition: TMP_LineInfo.cs:7
virtual void SetShaderDepth()
Set the Render Queue and ZTest mode on the current material
Definition: TMP_Text.cs:1522
virtual Material [] fontSharedMaterials
An array containing the materials used by the text object.
Definition: TMP_Text.cs:174
virtual void ComputeMarginSize()
Function to force an update of the margin size.
Definition: TMP_Text.cs:4544
int hashCode
The hash code corresponding to the name of this style.
Definition: TMP_Style.cs:24
static bool enableParseEscapeCharacters
Controls if Escape Characters will be parsed in the Text Input Box on newly created text objects.
Definition: TMP_Settings.cs:68
void SetText(StringBuilder text)
Set the text using a StringBuilder.
Definition: TMP_Text.cs:1858
Class which contains information about every element contained within the text object.
Definition: TMP_TextInfo.cs:13
void SetText(string text, bool syncTextInputBox)
Definition: TMP_Text.cs:1719
virtual void ClearMesh()
Function to clear the geometry of the Primary and Sub Text objects.
Definition: TMP_Text.cs:5521
void ParseInputText()
Method to parse the input text based on its source
Definition: TMP_Text.cs:1680
Bounds bounds
Returns the bounds of the mesh of the text object in world space.
Definition: TMP_Text.cs:1110
void ResetVertexLayout(bool isVolumetric)
float GetRenderedHeight(bool onlyVisibleCharacters)
Method returning the rendered height of the text object.
Definition: TMP_Text.cs:3667
virtual void FillSpriteVertexBuffers(int i, int index_X4)
Fill Vertex Buffers for Sprites
Definition: TMP_Text.cs:5112
bool ReplaceOpeningStyleTag(ref string sourceText, int srcIndex, out int srcOffset, ref int[] charBuffer, ref int writeIndex)
Method to handle inline replacement of style tag by opening style definition.
Definition: TMP_Text.cs:2577
TMP_Text linkedTextComponent
The linked text component used for flowing the text from one text component to another.
Definition: TMP_Text.cs:682
Vector2 GetPreferredValues(float width, float height)
Function to Calculate the Preferred Width and Height of the text object given the provided width and ...
Definition: TMP_Text.cs:3433
VertexGradient colorGradient
Sets the vertex colors for each of the 4 vertices of the character quads.
Definition: TMP_Text.cs:273
TextRenderFlags renderMode
Determines if the Mesh will be rendered.
Definition: TMP_Text.cs:905
virtual bool autoSizeTextContainer
Enables control over setting the size of the text container to match the text object.
Definition: TMP_Text.cs:1078
bool tintAllSprites
Determines whether or not the sprite color is multiplies by the vertex color of the text.
Definition: TMP_Text.cs:309
bool IsTagName(ref int[] text, string tag, int index)
Method to check for a matching rich text tag.
Definition: TMP_Text.cs:3172
bool useMaxVisibleDescender
Determines if the text's vertical alignment will be adjusted based on visible descender of the text.
Definition: TMP_Text.cs:973
float maxWidth
Definition: TMP_Text.cs:1238
static bool autoSizeTextContainer
Set the size of the text container of newly created text objects to match the size of the text.
float characterSpacing
Use the extents of the text geometry for alignment instead of font metrics.
Definition: TMP_Text.cs:536
bool ReplaceClosingStyleTag(ref StringBuilder sourceText, int srcIndex, ref int[] charBuffer, ref int writeIndex)
Method to handle inline replacement of style tag by closing style definition.
Definition: TMP_Text.cs:3066
float pixelsPerUnit
Definition: TMP_Text.cs:428
virtual void InternalCrossFadeColor(Color targetColor, float duration, bool ignoreTimeScale, bool useAlpha)
Definition: TMP_Text.cs:1665
FontStyles fontStyle
The style of the text
Definition: TMP_Text.cs:487
virtual void UpdateMeshPadding()
Function to be used to force recomputing of character padding when Shader / Material properties have ...
Definition: TMP_Text.cs:1621
float lineSpacing
The amount of additional spacing to add between each lines of text.
Definition: TMP_Text.cs:560
TMP_SpriteAsset spriteAsset
Default Sprite Asset used by the text object.
Definition: TMP_Text.cs:297
virtual void ClearMesh(bool uploadGeometry)
Function to clear the geometry of the Primary and Sub Text objects.
Definition: TMP_Text.cs:5527
void StringToCharArray(string sourceText, ref int[] charBuffer)
Method to store the content of a string into an integer array.
Definition: TMP_Text.cs:2286
int fontWeight
Control the weight of the font if an alternative font asset is assigned for the given weight in the f...
Definition: TMP_Text.cs:415
float GetRenderedWidth(bool onlyVisibleCharacters)
Method returning the rendered width of the text object.
Definition: TMP_Text.cs:3649
float flexibleWidth
Definition: TMP_Text.cs:1220
int GetUTF16(StringBuilder text, int i)
Convert UTF-16 Hex to Char
Definition: TMP_Text.cs:5698
virtual void SaveSpriteVertexInfo(Color32 vertexColor)
Store vertex information for each sprite.
Definition: TMP_Text.cs:4886
TMP_FontAsset GetFontAssetForWeight(int fontWeight)
Definition: TMP_Text.cs:5488
virtual Vector3 [] GetTextContainerLocalCorners()
Method to return the local corners of the Text Container or RectTransform.
Definition: TMP_Text.cs:1547
Color32 outlineColor
Sets the color of the _OutlineColor property of the assigned material. Changing outline color will re...
Definition: TMP_Text.cs:354
virtual Material [] GetSharedMaterials()
Method which returns an array containing the materials used by the text object.
Definition: TMP_Text.cs:1439
virtual void SetActiveSubMeshes(bool state)
Method to Enable or Disable child SubMesh objects.
Definition: TMP_Text.cs:5509
internal void SetTextInternal(string text)
Internal function used by the Text Input Field to populate TMP_TextInfo data.
Definition: TMP_Text.cs:1575
virtual void UpdateVertexData(TMP_VertexDataUpdateFlags flags)
Function to push the updated vertex data into the mesh and renderer.
Definition: TMP_Text.cs:1602
Bounds textBounds
Returns the bounds of the text of the text object.
Definition: TMP_Text.cs:1123
bool overrideColorTags
This overrides the color tags forcing the vertex colors to be the default font color.
Definition: TMP_Text.cs:323
static float defaultFontSize
The Default Point Size of newly created text objects.
int GetUTF32(string text, int i)
Convert UTF-32 Hex to Char
Definition: TMP_Text.cs:5714
void ResizeMeshInfo(int size)
Function to resized the content of MeshData and re-assign normals, tangents and triangles.
Base class which contains common properties and functions shared between the TextMeshPro and TextMesh...
Definition: TMP_Text.cs:110
static string defaultSpriteAssetPath
The relative path to a Resources folder in the project.
new Transform transform
Returns are reference to the Transform
Definition: TMP_Text.cs:1048
virtual Material CreateMaterialInstance(Material source)
Method to set the materials of the text and sub text objects.
Definition: TMP_Text.cs:1463
int GetUTF32(StringBuilder text, int i)
Convert UTF-32 Hex to Char
Definition: TMP_Text.cs:5733
TMP_VertexDataUpdateFlags
Flags to control what vertex data is pushed to the mesh and renderer.
static Vector2 defaultTextMeshProTextContainerSize
The Default Size of the Text Container of a TextMeshPro object.
void SetCharArray(char[] sourceText)
Character array containing the text to be displayed.
Definition: TMP_Text.cs:1882
float GetRenderedHeight()
Method returning the rendered height of the text object.
Definition: TMP_Text.cs:3658
bool IsTagName(ref StringBuilder text, string tag, int index)
Method to check for a matching rich text tag.
Definition: TMP_Text.cs:3191
bool parseCtrlCharacters
Enables or Disables parsing of CTRL characters in input text.
Definition: TMP_Text.cs:787
float GetPreferredHeight()
Method to calculate the preferred height of a text object.
Definition: TMP_Text.cs:3563
static TMP_Settings instance
Get a singleton instance of the settings class.
float flexibleHeight
Definition: TMP_Text.cs:1214
TextureMappingOptions horizontalMapping
Controls how the face and outline textures will be applied to the text object.
Definition: TMP_Text.cs:857
virtual Vector2 CalculatePreferredValues(float defaultFontSize, Vector2 marginSize, bool ignoreTextAutoSizing)
Method to calculate the preferred width and height of the text object.
Definition: TMP_Text.cs:3677
float ConvertToFloat(char[] chars, int startIndex, int length)
Extracts a float value from char[] assuming we know the position of the start, end and decimal point.
Definition: TMP_Text.cs:5894
virtual void ClearSubMeshObjects()
Destroy Sub Mesh Objects.
Definition: TMP_Text.cs:5515
void AddFloatToCharArray(float number, ref int index, int precision)
Function used in conjunction with SetText()
Definition: TMP_Text.cs:3326
Vector2 PackUV(float x, float y, float scale)
Function to pack scale information in the UV2 Channel.
Definition: TMP_Text.cs:5580
static bool TryGetColorGradientPreset(int hashCode, out TMP_ColorGradient gradientPreset)
Function returning the Color Gradient Preset corresponding to the provided hash code.
virtual void SetCulling()
Set the culling mode on the material.
Definition: TMP_Text.cs:1527
float characterWidthAdjustment
Percentage the width of characters can be adjusted before text auto-sizing begins to reduce the point...
Definition: TMP_Text.cs:598
Material fontMaterial
The material to be assigned to this text object. An instance of the material will be assigned to the ...
Definition: TMP_Text.cs:186
void Add(T item)
Function to add a new item to the stack.
new RectTransform rectTransform
Returns are reference to the RectTransform
Definition: TMP_Text.cs:1063
static bool enableTintAllSprites
Controls if TintAllSprites is enabled on newly created text objects by default.
Definition: TMP_Settings.cs:58
Bounds GetTextBounds(bool onlyVisibleCharacters)
Method which returns the bounds of the text object;
Definition: TMP_Text.cs:4463
virtual void ForceMeshUpdate(bool ignoreActiveState)
Method used for resetting vertex layout when switching to and from Volumetric Text mode.
Definition: TMP_Text.cs:1569
bool havePropertiesChanged
Property tracking if any of the text properties have changed. Flag is set before the text is regenera...
Definition: TMP_Text.cs:1024
int GetTagHashCode(ref char[] text, int index, out int closeIndex)
Get Hashcode for a given tag.
Definition: TMP_Text.cs:3236
_VerticalAlignmentOptions
Internal vertical text alignment options.
Definition: TMP_Text.cs:79
bool enableCulling
Sets the culling on the shaders. Note changing this value will result in an instance of the material.
Definition: TMP_Text.cs:822
void SetTextArrayToCharArray(char[] sourceText, ref int[] charBuffer)
Copies Content of formatted SetText() to charBuffer.
Definition: TMP_Text.cs:2211
static int AddMaterialReference(Material material, TMP_FontAsset fontAsset, MaterialReference[] materialReferences, Dictionary< int, int > materialReferenceIndexLookup)
Function to add a new material reference and returning its index in the material reference array.
bool isOrthographic
Sets Perspective Correction to Zero for Orthographic Camera mode & 0.875f for Perspective Camera mode...
Definition: TMP_Text.cs:810
virtual Vector4 margin
The margins of the text object.
Definition: TMP_Text.cs:997
Color32 faceColor
Sets the color of the _FaceColor property of the assigned material. Changing face color will result i...
Definition: TMP_Text.cs:335
virtual TMP_TextInfo GetTextInfo(string text)
Function used to evaluate the length of a text string.
Definition: TMP_Text.cs:4538
bool isTextOverflowing
Indicates if the text exceeds the vertical bounds of its text container.
Definition: TMP_Text.cs:662
void SetDefault(T item)
Function to set the first item on the stack and reset index.
int GetUTF16(string text, int i)
Convert UTF-16 Hex to Char
Definition: TMP_Text.cs:5683
virtual void SetFaceColor(Color32 color)
Function called internally to set the face color of the material. This will results in an instance of...
Definition: TMP_Text.cs:1505
float GetPreferredWidth()
Method to calculate the preferred width of a text object.
Definition: TMP_Text.cs:3505
virtual float preferredWidth
Computed preferred width of the text object.
Definition: TMP_Text.cs:1267
int GetTagHashCode(ref int[] text, int index, out int closeIndex)
Get Hashcode for a given tag.
Definition: TMP_Text.cs:3262
Vector2 GetPreferredValues(string text, float width, float height)
Function to Calculate the Preferred Width and Height of the text object given a certain string and si...
Definition: TMP_Text.cs:3482
virtual void SetVertices(Vector3[] vertices)
Function to push a new set of vertices to the mesh.
Definition: TMP_Text.cs:1615
int firstVisibleCharacter
The first character which should be made visible in conjunction with the Text Overflow Linked mode.
Definition: TMP_Text.cs:929
Dictionary< int, KerningPair > kerningDictionary
Dictionary containing the kerning data
virtual void InternalCrossFadeAlpha(float alpha, float duration, bool ignoreTimeScale)
Definition: TMP_Text.cs:1674
bool isVolumetricText
Determines if the geometry of the characters will be quads or volumetric (cubes).
Definition: TMP_Text.cs:1099
void SetText(string text, float arg0)
Definition: TMP_Text.cs:1752
Color32 HexCharsToColor(char[] hexChars, int startIndex, int length)
Method to convert Hex Color values to Color32
Definition: TMP_Text.cs:5836
float PackUV(float x, float y)
Definition: TMP_Text.cs:5600
TMP_FontAsset font
The Font Asset to be assigned to this text object.
Definition: TMP_Text.cs:141
TextOverflowModes overflowMode
Definition: TMP_Text.cs:650
void StringBuilderToIntArray(StringBuilder sourceText, ref int[] charBuffer)
Copy contents of StringBuilder into int array.
Definition: TMP_Text.cs:2431
void SetText(string text)
Definition: TMP_Text.cs:1709
static void AddColorGradientPreset(int hashCode, TMP_ColorGradient spriteAsset)
Add new Color Gradient Preset to dictionary.
virtual Material [] fontMaterials
The materials to be assigned to this text object. An instance of the materials will be assigned.
Definition: TMP_Text.cs:213
virtual void ForceMeshUpdate()
Function to force the regeneration of the text object.
Definition: TMP_Text.cs:1555
float paragraphSpacing
The amount of additional spacing to add between each lines of text.
Definition: TMP_Text.cs:586
virtual void FillCharacterVertexBuffers(int i, int index_X4)
Store vertex attributes into the appropriate TMP_MeshInfo.
Definition: TMP_Text.cs:4977
virtual void DrawUnderlineMesh(Vector3 start, Vector3 end, ref int index, float startScale, float endScale, float maxScale, float sdfScale, Color32 underlineColor)
Method to add the underline geometry.
Definition: TMP_Text.cs:5167
float minWidth
Definition: TMP_Text.cs:1226
static bool enableWordWrapping
Controls if Word Wrapping will be enabled on newly created text objects by default.
Definition: TMP_Settings.cs:28
virtual void UpdateVertexData()
Function to push the updated vertex data into the mesh and renderer.
Definition: TMP_Text.cs:1608
TextureMappingOptions verticalMapping
Controls how the face and outline textures will be applied to the text object.
Definition: TMP_Text.cs:869
LayoutElement layoutElement
Definition: TMP_Text.cs:1251
bool ValidateHtmlTag(int[] chars, int startIndex, out int endIndex)
Function to identify and validate the rich tag. Returns the position of the > if the tag was valid.
Definition: TMP_Text.cs:5979
bool isUsingBold
Property used in conjunction with padding calculation for the geometry.
Definition: TMP_Text.cs:499
static bool enableExtraPadding
Controls if Extra Padding is enabled on newly created text objects by default.
Definition: TMP_Settings.cs:48
void SetTextSortingOrder(VertexSortingOrder order)
Function to control the sorting of the geometry of the text object.
Definition: TMP_Text.cs:1487
virtual void SetSharedMaterial(Material mat)
Function called internally when a new shared material is assigned via the fontSharedMaterial property...
Definition: TMP_Text.cs:1422
Vector2 GetPreferredValues(string text)
Function to Calculate the Preferred Width and Height of the text object given a certain string.
Definition: TMP_Text.cs:3458
float fontSizeMax
Maximum point size of the font when text auto-sizing is enabled.
Definition: TMP_Text.cs:475
TMP_SpriteAnimator spriteAnimator
Component used to control wrapping of text following some arbitrary shape.
Definition: TMP_Text.cs:1177
virtual Material GetMaterial(Material mat)
Function called internally when a new material is assigned via the fontMaterial property.
Definition: TMP_Text.cs:1427
float GetPreferredWidth(Vector2 margin)
Method to calculate the preferred width of a text object.
Definition: TMP_Text.cs:3541
bool ReplaceClosingStyleTag(ref int[] sourceText, int srcIndex, ref int[] charBuffer, ref int writeIndex)
Method to handle inline replacement of style tag by closing style definition.
Definition: TMP_Text.cs:2929
static TMP_SpriteAsset SearchForSpriteByHashCode(TMP_SpriteAsset spriteAsset, int hashCode, bool includeFallbacks, out int spriteIndex)
Search the given sprite asset and fallbacks for a sprite whose hash code value of its name matches th...
float maxHeight
Definition: TMP_Text.cs:1244
int firstOverflowCharacterIndex
The first character which exceeds the vertical bounds of its text container.
Definition: TMP_Text.cs:671
virtual float renderedWidth
Compute the rendered width of the text object.
Definition: TMP_Text.cs:1286
int maxVisibleCharacters
Allows to control how many characters are visible from the input.
Definition: TMP_Text.cs:940
bool isRightToLeftText
Definition: TMP_Text.cs:129
TMP_ColorGradient colorGradientPreset
Set the vertex colors of the 4 vertices of each character quads.
Definition: TMP_Text.cs:285
float GetRenderedWidth()
Method returning the rendered width of the text object.
Definition: TMP_Text.cs:3640
virtual void GenerateTextMesh()
Method which parses the text input, does the layout of the text as well as generating the geometry.
Definition: TMP_Text.cs:3404
bool extraPadding
Adds extra padding around each character. This may be necessary when the displayed text is very small...
Definition: TMP_Text.cs:761
bool IsTagName(ref string text, string tag, int index)
Method to check for a matching rich text tag.
Definition: TMP_Text.cs:3134
Bounds GetTextBounds()
Method which returns the bounds of the text object;
Definition: TMP_Text.cs:4431
void SetCharArray(char[] sourceText, int start, int length)
Character array containing the text to be displayed.
Definition: TMP_Text.cs:1986
bool enableKerning
Determines if kerning is enabled or disabled.
Definition: TMP_Text.cs:749
virtual Material fontSharedMaterial
The material to be assigned to this text object.
Definition: TMP_Text.cs:155
void AddIntToCharArray(int number, ref int index, int precision)
// Function used in conjunction with SetText()
Definition: TMP_Text.cs:3363
float outlineWidth
Sets the thickness of the outline of the font. Setting this value will result in an instance of the m...
Definition: TMP_Text.cs:373
int maxVisibleWords
Allows to control how many words are visible from the input.
Definition: TMP_Text.cs:951
int HexToInt(char hex)
Function to pack scale information in the UV2 Channel.
Definition: TMP_Text.cs:5647
void ResizeLineExtents(int size)
Function to increase the size of the Line Extents Array.
Definition: TMP_Text.cs:4505
float wordSpacing
The amount of additional spacing between words.
Definition: TMP_Text.cs:549
static Vector2 defaultTextMeshProUITextContainerSize
The Default Width of the Text Container of a TextMeshProUI object.
Vector2 GetRenderedValues(bool onlyVisibleCharacters)
Definition: TMP_Text.cs:3630
float wordWrappingRatios
Controls the blending between using character and word spacing to fill-in the space for justified tex...
Definition: TMP_Text.cs:625
int GetAttributeParameters(char[] chars, int startIndex, int length, ref float[] parameters)
Method which returns the number of parameters used in a tag attribute and populates an array with suc...
Definition: TMP_Text.cs:5868
static void AddSpriteAsset(TMP_SpriteAsset spriteAsset)
Add new Sprite Asset to dictionary.
TMP custom data type to represent 32 bit characters.
_HorizontalAlignmentOptions
Internal horizontal text alignment options.
Definition: TMP_Text.cs:71
bool isTextTruncated
Property indicating whether the text is Truncated or using Ellipsis.
Definition: TMP_Text.cs:740
int RestoreWordWrappingState(ref WordWrapState state)
Restore the State of various variables used in the mesh creation loop.
Definition: TMP_Text.cs:4682
void SetText(string text, float arg0, float arg1, float arg2)
Definition: TMP_Text.cs:1779
int pageToDisplay
Controls which page of text is shown
Definition: TMP_Text.cs:985
float lineSpacingAdjustment
The amount of potential line spacing adjustment before text auto sizing kicks in.
Definition: TMP_Text.cs:574
virtual float GetPaddingForMaterial(Material mat)
Get the padding value for the given material
Definition: TMP_Text.cs:1540
float ConvertToFloat(char[] chars, int startIndex, int length, out int lastIndex)
Extracts a float value from char[] given a start index and length.
Definition: TMP_Text.cs:5909
void SetTextSortingOrder(int[] order)
Function to sort the geometry of the text object in accordance to the provided order.
Definition: TMP_Text.cs:1496
float fontScale
The scale of the current text.
Definition: TMP_Text.cs:406
void ResizeInternalArray< T >(ref T[] array)
Definition: TMP_Text.cs:3310
static void AddFontMaterial(int hashCode, Material material)
Add new Material reference to dictionary.
static void AddFontAsset(TMP_FontAsset fontAsset)
Add new font asset reference to dictionary.
virtual void SetOutlineThickness(float thickness)
Function called internally to set the outline thickness property of the material. This will results i...
Definition: TMP_Text.cs:1517
virtual float GetPaddingForMaterial()
Get the padding value for the currently assigned material
Definition: TMP_Text.cs:1533
bool enableWordWrapping
Controls whether or not word wrapping is applied. When disabled, the text will be displayed on a sing...
Definition: TMP_Text.cs:611
void GetSpecialCharacters(TMP_FontAsset fontAsset)
Method used to find and cache references to the Underline and Ellipsis characters.
Definition: TMP_Text.cs:5434
FaceInfo fontInfo
The general information about the font.
int layoutPriority
Definition: TMP_Text.cs:1298
override Color color
This is the default vertex color assigned to each vertices. Color tags will override vertex colors un...
Definition: TMP_Text.cs:228
virtual void AdjustLineOffset(int startIndex, int endIndex, float offset)
Method to adjust line spacing as a result of using different fonts or font point size.
Definition: TMP_Text.cs:4498
void SetCharArray(int[] sourceText, int start, int length)
Character array containing the text to be displayed.
Definition: TMP_Text.cs:2099
virtual void SetOutlineColor(Color32 color)
Function called internally to set the outline color of the material. This will results in an instance...
Definition: TMP_Text.cs:1511
int GetTagHashCode(ref StringBuilder text, int index, out int closeIndex)
Get Hashcode for a given tag.
Definition: TMP_Text.cs:3288
string text
A string containing the text to be displayed.
Definition: TMP_Text.cs:116
bool ReplaceClosingStyleTag(ref char[] sourceText, int srcIndex, ref int[] charBuffer, ref int writeIndex)
Method to handle inline replacement of style tag by closing style definition.
Definition: TMP_Text.cs:2998
bool richText
Enables or Disables Rich Text Tags
Definition: TMP_Text.cs:775
static TMP_Style GetStyle(int hashCode)
Function to retrieve the Style matching the HashCode.
Class that contains the basic information about the font.
bool enableAutoSizing
Enable text auto-sizing
Definition: TMP_Text.cs:449
static float defaultTextAutoSizingMaxRatio
The multiplier used to computer the default Max point size when Text Auto Sizing is used.
void ReplaceTagWithCharacter(int[] chars, int insertionIndex, int tagLength, char c)
Replace a given number of characters (tag) in the array with a new character and shift subsequent cha...
Definition: TMP_Text.cs:5459
virtual float renderedHeight
Compute the rendered height of the text object.
Definition: TMP_Text.cs:1292
static bool TryGetMaterial(int hashCode, out Material material)
Function returning the Font Material corresponding to the provided hash code.
void LoadDefaultSettings()
Internal function used to load the default settings of text objects.
Definition: TMP_Text.cs:5394
bool IsTagName(ref char[] text, string tag, int index)
Method to check for a matching rich text tag.
Definition: TMP_Text.cs:3153
static bool TryGetSpriteAsset(int hashCode, out TMP_SpriteAsset spriteAsset)
Function returning the Sprite Asset corresponding to the provided hash code.
virtual string GetParsedText()
Function which returns the text after it has been parsed and rich text tags removed.
Definition: TMP_Text.cs:5534
static bool warningsDisabled
Controls the display of warning message in the console.
Definition: TMP_Settings.cs:88
static string defaultColorGradientPresetsPath
The relative path to a Resources folder in the project that contains Color Gradient Presets.
float minHeight
Definition: TMP_Text.cs:1232
static bool TryGetFontAsset(int hashCode, out TMP_FontAsset fontAsset)
Function returning the Font Asset corresponding to the provided hash code.
int GetTagHashCode(ref string text, int index, out int closeIndex)
Get Hashcode for a given tag.
Definition: TMP_Text.cs:3210
bool ignoreVisibility
Forces objects that are not visible to get refreshed.
Definition: TMP_Text.cs:845
bool ReplaceOpeningStyleTag(ref char[] sourceText, int srcIndex, out int srcOffset, ref int[] charBuffer, ref int writeIndex)
Method to handle inline replacement of style tag by opening style definition.
Definition: TMP_Text.cs:2719
bool enableVertexGradient
Determines if Vertex Color Gradient should be used
Definition: TMP_Text.cs:258
TextAlignmentOptions alignment
Text alignment options
Definition: TMP_Text.cs:507
float fontSizeMin
Minimum point size of the font when text auto-sizing is enabled.
Definition: TMP_Text.cs:463
bool ignoreRectMaskCulling
Controls whether or not the text object will be culled when using a 2D Rect Mask.
Definition: TMP_Text.cs:833
bool isOverlay
Sets the RenderQueue along with Ztest to force the text to be drawn last and on top of scene elements...
Definition: TMP_Text.cs:799
virtual void LoadFontAsset()
Method which derived classes need to override to load Font Assets.
Definition: TMP_Text.cs:1416
Structure used to track basic XML tags which are binary (on / off)
float GetPreferredHeight(Vector2 margin)
Method to calculate the preferred height of a text object.
Definition: TMP_Text.cs:3598
void SaveWordWrappingState(ref WordWrapState state, int index, int count)
Function used in conjunction with GetTextInfo to figure out Array allocations.
Definition: TMP_Text.cs:4604
bool ReplaceClosingStyleTag(ref string sourceText, int srcIndex, ref int[] charBuffer, ref int writeIndex)
Method to handle inline replacement of style tag by closing style definition.
Definition: TMP_Text.cs:2860
static float defaultTextAutoSizingMinRatio
The multiplier used to computer the default Min point size when Text Auto Sizing is used.
bool ReplaceOpeningStyleTag(ref int[] sourceText, int srcIndex, out int srcOffset, ref int[] charBuffer, ref int writeIndex)
Method to handle inline replacement of style tag by opening style definition.
Definition: TMP_Text.cs:2648
virtual Mesh mesh
The mesh used by the font asset and material assigned to the text object.
Definition: TMP_Text.cs:1089
override void CrossFadeColor(Color targetColor, float duration, bool ignoreTimeScale, bool useAlpha)
Definition: TMP_Text.cs:1637
static TMP_SpriteAsset defaultSpriteAsset
The Default Sprite Asset to be used by default.
Color32 HexCharsToColor(char[] hexChars, int tagCount)
Method to convert Hex color values to Color32
Definition: TMP_Text.cs:5754
TMP_TextInfo textInfo
Returns data about the text object which includes information about each character,...
Definition: TMP_Text.cs:1014
static LineBreakingTable linebreakingRules