| using System.Collections; | 
| using System.Collections.Generic; | 
| using System.Text.RegularExpressions; | 
| using UnityEngine; | 
| using UnityEngine.UI; | 
| using UnityEngine.EventSystems; | 
| using System; | 
| using System.Linq; | 
| using System.Text; | 
| public class RichText : Text, IPointerClickHandler | 
| { | 
|     /// <summary> | 
|     /// 最终显示文本 | 
|     /// </summary> | 
|     private string m_OutputText; | 
|   | 
|     private string m_RichText = string.Empty; | 
|   | 
|     public Action OnClick; | 
|   | 
|     #region 对外参数 | 
|     [SerializeField] | 
|     private float m_ImgDeltay = 0; | 
|     public float ImgDeltay | 
|     { | 
|         get | 
|         { | 
|             return m_ImgDeltay; | 
|         } | 
|         set | 
|         { | 
|             m_ImgDeltay = value; | 
|             SetVerticesDirty(); | 
|         } | 
|     } | 
|   | 
|     [SerializeField] | 
|     private float m_unlineDeltay = 0; | 
|     public float UnlineDeltay | 
|     { | 
|         get | 
|         { | 
|             return m_unlineDeltay; | 
|         } | 
|         set | 
|         { | 
|             m_unlineDeltay = value; | 
|         } | 
|     } | 
|   | 
|     [SerializeField] | 
|     private float m_unlineHeight = 1; | 
|     public float UnlineHeight | 
|     { | 
|         get | 
|         { | 
|             return m_unlineHeight; | 
|         } | 
|         set | 
|         { | 
|             m_unlineHeight = value; | 
|         } | 
|     } | 
|     [SerializeField] | 
|     private float m_faceSize = 32; | 
|     public float FaceSize | 
|     { | 
|         get | 
|         { | 
|             return m_faceSize; | 
|         } | 
|         set | 
|         { | 
|             m_faceSize = value; | 
|         } | 
|     } | 
|     [SerializeField] | 
|     private bool m_unline = true; | 
|     public bool Unline | 
|     { | 
|         get { return m_unline; } | 
|         set { m_unline = value; } | 
|     } | 
|     [SerializeField] | 
|     private bool m_HrefClick = true; | 
|     public bool HrefClick | 
|     { | 
|         get { return m_HrefClick; } | 
|         set { m_HrefClick = value; } | 
|     } | 
|     [SerializeField] | 
|     private string m_EnableDisplay; | 
|     public string enableDisplay | 
|     { | 
|         get { return m_EnableDisplay; } | 
|         set { m_EnableDisplay = value; } | 
|     } | 
|     [SerializeField] | 
|     private bool m_Language = false; | 
|     public bool language | 
|     { | 
|         get { return m_Language; } | 
|         set { m_Language = value; } | 
|     } | 
|     [SerializeField] | 
|     private bool m_AutoNewLine = false; | 
|     public bool AutoNewLine | 
|     { | 
|         get | 
|         { | 
|             return m_AutoNewLine; | 
|         } | 
|         set | 
|         { | 
|             m_AutoNewLine = value; | 
|             SetRichTextDirty(); | 
|         } | 
|     } | 
|   | 
|     [SerializeField] | 
|     private bool m_LockImgSize = false; | 
|     public bool LockImgSize | 
|     { | 
|         get | 
|         { | 
|             return m_LockImgSize; | 
|         } | 
|         set | 
|         { | 
|             m_LockImgSize = value; | 
|         } | 
|     } | 
|   | 
|     [SerializeField] | 
|     private bool m_ModifyImgSize = false; | 
|     public bool ModifyImgSiez | 
|     { | 
|         get { return m_ModifyImgSize; } | 
|         set { m_ModifyImgSize = value; } | 
|     } | 
|   | 
|     [SerializeField] | 
|     private float m_ModifyImgWidth = 0; | 
|     public float ModifyImgWidth | 
|     { | 
|         get { return m_ModifyImgWidth; } | 
|         set { m_ModifyImgWidth = value; } | 
|     } | 
|   | 
|     [SerializeField] | 
|     private float m_ModifyImgHeight = 0; | 
|     public float ModifyImgHeight | 
|     { | 
|         get { return m_ModifyImgHeight; } | 
|         set { m_ModifyImgHeight = value; } | 
|     } | 
|   | 
|     [SerializeField] | 
|     private ColorType m_ColorType = ColorType.Dark; | 
|     public ColorType colorType | 
|     { | 
|         get { return m_ColorType; } | 
|         set { m_ColorType = value; } | 
|     } | 
|   | 
|     public enum ColorType | 
|     { | 
|         Dark, | 
|         Bright, | 
|     } | 
|     #endregion | 
|   | 
|     protected override void Awake() | 
|     { | 
| #if UNITY_EDITOR | 
|         if (UnityEditor.PrefabUtility.GetPrefabType(this) == UnityEditor.PrefabType.Prefab) | 
|         { | 
|             return; | 
|         } | 
| #endif  | 
|         unline = transform.GetComponentInChildren<TextUnline>(); | 
|         if (unline == null) | 
|         { | 
|             GameObject obj = BuiltInLoader.LoadPrefab("TextUnline"); | 
|             // GameObject obj = UILoader.LoadPrefab("TextUnline") as GameObject; | 
|             obj = Instantiate(obj); | 
|             obj.transform.SetParent(transform); | 
|             obj.transform.localScale = Vector3.one; | 
|             unline = obj.GetComponent<TextUnline>(); | 
|             unline.raycastTarget = false; | 
|         } | 
|     } | 
|   | 
|     protected override void OnEnable() | 
|     { | 
|         base.OnEnable(); | 
| #if UNITY_EDITOR | 
|         if (UnityEditor.PrefabUtility.GetPrefabType(this) == UnityEditor.PrefabType.Prefab) | 
|         { | 
|             return; | 
|         } | 
| #endif  | 
|         if (language && !string.IsNullOrEmpty(enableDisplay) && Application.isPlaying/* && ConfigInitiator.done*/) | 
|         { | 
|             text = Language.Get(enableDisplay); | 
|         } | 
|     } | 
|   | 
|     #region 绘制 | 
|     private UIVertex vert = new UIVertex(); | 
|     protected override void OnPopulateMesh(VertexHelper toFill) | 
|     { | 
|         if (font == null) return; | 
|         toFill.Clear(); | 
|         base.OnPopulateMesh(toFill); | 
|         CalcBounds(toFill); | 
|         #region 修改图片位置 | 
|         if (m_ImgList == null) return; | 
|         for (int i = 0; i < m_ImgList.Count; i++) | 
|         { | 
|             int _imgEnd = m_ImgList[i].end; | 
|             RectTransform rt = m_ImgPool[i].rectTransform; | 
|             Vector2 _imgSize = rt.sizeDelta; | 
|             if (_imgEnd < toFill.currentIndexCount) | 
|             { | 
|                 try | 
|                 { | 
|                     toFill.PopulateUIVertex(ref vert, _imgEnd); | 
|                     rt.localPosition = new Vector2(vert.position.x + _imgSize.x / 2, vert.position.y + _imgSize.y / 2 - m_ImgDeltay); | 
|                     toFill.PopulateUIVertex(ref vert, _imgEnd - 3); | 
|                     Vector3 pos = vert.position; | 
|                     for (int j = _imgEnd, k = _imgEnd - 3; j >= k; j--) | 
|                     { | 
|                         toFill.PopulateUIVertex(ref vert, j); | 
|                         pos.y = Mathf.Min(pos.y, vert.position.y - ImgDeltay); | 
|                         vert.position = pos; | 
|                         toFill.SetUIVertex(vert, j); | 
|                     } | 
|                 } | 
|                 catch (System.Exception) | 
|                 { | 
|                     continue; | 
|                 } | 
|   | 
|             } | 
|         } | 
|         #endregion | 
|     } | 
|   | 
|     public override void SetVerticesDirty() | 
|     { | 
|         base.SetVerticesDirty(); | 
| #if UNITY_EDITOR | 
|         if (UnityEditor.PrefabUtility.GetPrefabType(this) == UnityEditor.PrefabType.Prefab) | 
|         { | 
|             return; | 
|         } | 
| #endif  | 
|         //m_OutputText = GetOutputText(m_RichText); | 
|   | 
|         GenerateImg(); | 
|     } | 
|     #endregion | 
|   | 
|     #region 解析 | 
|     private string GetOutputText(string _text) | 
|     { | 
|         string result = _text; | 
|         result = GetExtenalData(result); | 
|         result = GetTaskInfo(result); | 
|         result = RichTextMgr.Inst.Analysis(result, out m_ImgList, out m_HrefList, this); | 
|         return result; | 
|     } | 
|     #endregion | 
|   | 
|     #region 图片 | 
|     private List<RichTextMgr.ImgInfo> m_ImgList; | 
|     private List<Image> m_ImgPool = new List<Image>(); | 
|     private void GenerateImg() | 
|     { | 
|         if (m_ImgList == null) return; | 
|         m_ImgPool.Clear(); | 
|         GetComponentsInChildren(true, m_ImgPool); | 
|         for (int i = 0; i < m_ImgList.Count; i++) | 
|         { | 
|             RichTextMgr.ImgInfo imgInfo = m_ImgList[i]; | 
|             Image img; | 
|             if (i >= m_ImgPool.Count) | 
|             { | 
|                 img = CreateImg(); | 
|                 m_ImgPool.Add(img); | 
|             } | 
|             else | 
|             { | 
|                 img = m_ImgPool[i]; | 
|             } | 
|             img.SetActive(true); | 
|             img.raycastTarget = HrefClick; | 
|             img.sprite = imgInfo.sprite; | 
|             Vector2 _imgSize = new Vector2(imgInfo.width, imgInfo.height); | 
|             img.rectTransform.sizeDelta = _imgSize; | 
|             UIFrame frame = img.GetComponent<UIFrame>(); | 
|             if (imgInfo.IsFace) | 
|             { | 
|                 if (frame == null) frame = img.gameObject.AddComponent<UIFrame>(); | 
|                 img.raycastTarget = false; | 
|                 frame.ResetFrame(imgInfo.spriteName); | 
|                 frame.enabled = true; | 
|             } | 
|             else | 
|             { | 
|                 if (frame != null) frame.enabled = false; | 
|             } | 
|         } | 
|   | 
|         for (int i = m_ImgPool.Count - 1; i >= m_ImgList.Count; i--) | 
|         { | 
|             m_ImgPool[i].SetActive(false); | 
|         } | 
|     } | 
|   | 
|     private Image CreateImg() | 
|     { | 
|         DefaultControls.Resources res = new DefaultControls.Resources(); | 
|         GameObject go = DefaultControls.CreateImage(res); | 
|         go.layer = gameObject.layer; | 
|         RectTransform rt = go.transform as RectTransform; | 
|         if (rt != null) | 
|         { | 
|             rt.SetParent(rectTransform); | 
|             rt.localPosition = Vector3.zero; | 
|             rt.localRotation = Quaternion.identity; | 
|             rt.localScale = Vector3.one; | 
|         } | 
|         Image img = go.GetComponent<Image>(); | 
|         return img; | 
|     } | 
|     #endregion | 
|   | 
|     #region 下划线||超链接 | 
|     [SerializeField] | 
|     private TextUnline unline; | 
|     private List<RichTextMgr.HrefInfo> m_HrefList; | 
|     private Dictionary<int,float> m_UnlineBottomDict = new Dictionary<int,float>(); | 
|     private float GetUnlineHeight(int _line) | 
|     { | 
|         foreach (var _key in m_UnlineBottomDict.Keys) | 
|         { | 
|             if (_line <= _key) | 
|             { | 
|                 return m_UnlineBottomDict[_key]; | 
|             } | 
|         } | 
|         return m_UnlineBottomDict.Values.Last(); | 
|     } | 
|   | 
|     public string GetHrefMessage(string _key) | 
|     { | 
|         if (m_HrefList != null) | 
|         { | 
|             for (int i = 0; i < m_HrefList.Count; i++) | 
|             { | 
|                 if (m_HrefList[i].mSplits.ContainsKey(_key)) | 
|                 { | 
|                     return m_HrefList[i].mSplits[_key]; | 
|                 } | 
|             } | 
|         } | 
|         return string.Empty; | 
|     } | 
|   | 
|     private void CalcBounds(VertexHelper toFill) | 
|     { | 
|         if (unline != null) unline.ClearVert(); | 
|         if (m_HrefList == null) return; | 
|         float minBottom = 0; | 
|         if (!Unline) | 
|         { | 
|             return; | 
|         } | 
|         m_UnlineBottomDict.Clear(); | 
|         int _line = 0; | 
|         bool _note = false; | 
|         foreach (RichTextMgr.HrefInfo hrefInfo in m_HrefList) | 
|         { | 
|             CalcUnline(toFill, hrefInfo); | 
|             if (!hrefInfo.unline) | 
|             { | 
|                 continue; | 
|             } | 
|             hrefInfo.lines.Clear(); | 
|             for (int i = 0; i < hrefInfo.boxs.Count; i++) | 
|             { | 
|                 Vector3 start = hrefInfo.boxs[i].position; | 
|                 if (minBottom == 0 && !_note) | 
|                 { | 
|                     minBottom = start.y; | 
|                     _note = true; | 
|                 } | 
|                 if (Math.Abs(minBottom - start.y) >= fontSize / 2) | 
|                 { | 
|                     m_UnlineBottomDict.Add(_line, minBottom); | 
|                     minBottom = start.y; | 
|                     _line++; | 
|                 } | 
|                 else | 
|                 { | 
|                     minBottom = Mathf.Min(start.y, minBottom); | 
|                 } | 
|                 hrefInfo.lines.Add(_line); | 
|             } | 
|         } | 
|         m_UnlineBottomDict.Add(_line, minBottom); | 
|         foreach (RichTextMgr.HrefInfo hrefInfo in m_HrefList) | 
|         { | 
|             if (!hrefInfo.unline) | 
|             { | 
|                 continue; | 
|             } | 
|             for (int i = 0; i < hrefInfo.boxs.Count; i++) | 
|             { | 
|                 Vector3 start = hrefInfo.boxs[i].position; | 
|                 var _unlineline = i < hrefInfo.lines.Count ? hrefInfo.lines[i] : 0; | 
|                 start.y = GetUnlineHeight(_unlineline); | 
|                 Vector3 end = start; | 
|                 end.x += hrefInfo.boxs[i].width; | 
|                 unline.SetUIVertex(start, end, -UnlineDeltay, m_unlineHeight, hrefInfo.unlineColor); | 
|             } | 
|         } | 
|     } | 
|   | 
|     private void CalcUnline(VertexHelper toFill, RichTextMgr.HrefInfo hrefInfo) | 
|     { | 
|         hrefInfo.boxs.Clear(); | 
|         if (hrefInfo.start >= toFill.currentIndexCount) return; | 
|         try | 
|         { | 
|             toFill.PopulateUIVertex(ref vert, hrefInfo.start); | 
|         } | 
|         catch (System.Exception) | 
|         { | 
|             return; | 
|         } | 
|         Vector3 pos = vert.position; | 
|         var realStart = hrefInfo.start; | 
|         ///-----为了过滤颜色导致多次添加包围盒 | 
|         while (realStart <= hrefInfo.end) | 
|         { | 
|             try | 
|             { | 
|                 toFill.PopulateUIVertex(ref vert, realStart); | 
|                 if (pos != vert.position) | 
|                 { | 
|                     if (realStart <= hrefInfo.start + 1) | 
|                     { | 
|                         realStart = hrefInfo.start; | 
|                     } | 
|                     else | 
|                     { | 
|                         pos = vert.position; | 
|                     } | 
|                     break; | 
|                 } | 
|             } | 
|             catch (Exception) | 
|             { | 
|                 return; | 
|             } | 
|             realStart++; | 
|         } | 
|         Bounds bounds = new Bounds(pos, Vector3.zero); | 
|         int _Cnt = 0; | 
|         for (int i = realStart, k = hrefInfo.end; i <= k; i++) | 
|         { | 
|             if (i >= toFill.currentIndexCount) break; | 
|             try | 
|             { | 
|                 toFill.PopulateUIVertex(ref vert, i); | 
|             } | 
|             catch (System.Exception) | 
|             { | 
|                 break; | 
|             } | 
|             pos = vert.position; | 
|             if (pos.x - 0.1 <= bounds.min.x && _Cnt > 3) | 
|             { | 
|                 hrefInfo.boxs.Add(new Rect(bounds.min, bounds.size)); | 
|                 bounds = new Bounds(pos, Vector3.zero); | 
|                 _Cnt = 0; | 
|             } | 
|             bounds.Encapsulate(pos); | 
|             _Cnt++; | 
|         } | 
|         hrefInfo.boxs.Add(new Rect(bounds.min, bounds.size)); | 
|     } | 
|     #endregion | 
|   | 
|     #region 自适应 | 
|     public override float preferredWidth | 
|     { | 
|         get | 
|         { | 
|             if (font == null && Application.isPlaying) | 
|             { | 
|                 font = FontUtility.preferred; | 
|             } | 
|             var settings = GetGenerationSettings(Vector2.zero); | 
|             return cachedTextGeneratorForLayout.GetPreferredWidth(m_OutputText, settings) / pixelsPerUnit; | 
|         } | 
|     } | 
|   | 
|     public override float preferredHeight | 
|     { | 
|         get | 
|         { | 
|             if (font == null && Application.isPlaying) | 
|             { | 
|                 font = FontUtility.preferred; | 
|             } | 
|             var settings = GetGenerationSettings(new Vector2(rectTransform.rect.size.x, 0.0f)); | 
|             float _height = cachedTextGeneratorForLayout.GetPreferredHeight(m_OutputText, settings) / pixelsPerUnit; | 
|             return _height; | 
|         } | 
|     } | 
|     #endregion | 
|   | 
|     #region 外部数据 | 
|     private static readonly string FORMAT_PATTERN = @"\%s([0-9]+)"; | 
|   | 
|     private ArrayList extenalData = new ArrayList(); | 
|   | 
|     public void SetExtenalData(params object[] msg) | 
|     { | 
|         extenalData.Clear(); | 
|         if (msg != null && msg.Length > 0) | 
|         { | 
|             extenalData.AddRange(msg); | 
|         } | 
|     } | 
|   | 
|     public void SetExtenalData(ICollection collection) | 
|     { | 
|         extenalData.Clear(); | 
|         if (collection != null && collection.Count > 0) | 
|         { | 
|             extenalData.AddRange(collection); | 
|             collection = null; | 
|         } | 
|     } | 
|   | 
|     private string GetExtenalData(string val) | 
|     { | 
|         textBuilder.Length = 0; | 
|         int index = 0; | 
|         if (Regex.IsMatch(val, FORMAT_PATTERN)) | 
|         { | 
|             foreach (Match match in Regex.Matches(val, FORMAT_PATTERN)) | 
|             { | 
|                 textBuilder.Append(val.Substring(index, match.Index - index)); | 
|                 int infoIndex = 0; | 
|                 int.TryParse(match.Groups[1].Value, out infoIndex); | 
|                 if (extenalData != null && infoIndex < extenalData.Count) | 
|                 { | 
|                     textBuilder.Append(extenalData[infoIndex]); | 
|                 } | 
|                 else | 
|                 { | 
|                     textBuilder.Append(0); | 
|                 } | 
|                 index = match.Index + match.Length; | 
|             } | 
|             textBuilder.Append(val.Substring(index, val.Length - index)); | 
|             return textBuilder.ToString(); | 
|         } | 
|         else | 
|         { | 
|             return val; | 
|         } | 
|     } | 
|     #region 任务数据 | 
|     private Dictionary<string, string> extenalDataDic = null; | 
|     private const string Info_Pattern = "{([a-zA-Z0-9_]+)}"; | 
|     public void SetReplaceInfo(Dictionary<string, string> _infoDic) | 
|     { | 
|         extenalDataDic = _infoDic; | 
|         SetRichTextDirty(); | 
|     } | 
|   | 
|     private string GetTaskInfo(string val) | 
|     { | 
|         textBuilder.Length = 0; | 
|         int index = 0; | 
|         if (Regex.IsMatch(val, Info_Pattern)) | 
|         { | 
|             foreach (Match match in Regex.Matches(val, Info_Pattern)) | 
|             { | 
|                 textBuilder.Append(val.Substring(index, match.Index - index)); | 
|                 if (extenalDataDic != null && extenalDataDic.ContainsKey(match.Groups[1].Value)) | 
|                 { | 
|                     textBuilder.Append(extenalDataDic[match.Groups[1].Value]); | 
|                 } | 
|                 else | 
|                 { | 
|                     textBuilder.Append(0); | 
|                 } | 
|                 index = match.Index + match.Length; | 
|             } | 
|             textBuilder.Append(val.Substring(index, val.Length - index)); | 
|             return textBuilder.ToString(); | 
|         } | 
|         else | 
|         { | 
|             return val; | 
|         } | 
|     } | 
|     #endregion | 
|     #endregion | 
|   | 
|     #region 执行事件 | 
|     public void OnPointerClick(PointerEventData eventData) | 
|     { | 
|         if (HrefClick) | 
|         { | 
|             Vector2 lp; | 
|             RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, | 
|                 eventData.position, eventData.pressEventCamera, out lp); | 
|             if (m_HrefList != null) | 
|             { | 
|                 foreach (var hrefInfo in m_HrefList) | 
|                 { | 
|                     List<Rect> boxs = hrefInfo.boxs; | 
|                     for (int i = 0; i < boxs.Count; i++) | 
|                     { | 
|                         if (boxs[i].Contains(lp)) | 
|                         { | 
|                             hrefInfo.Execute(); | 
|                             return; | 
|                         } | 
|                     } | 
|                 } | 
|             } | 
|         } | 
|         if (OnClick != null) OnClick(); | 
|     } | 
|   | 
|     public void OnImgClick() | 
|     { | 
|     } | 
|   | 
|     public void ExcuteHref(int eventIndex = 0, int hrefIndex = 0) | 
|     { | 
|         if (m_HrefList == null || m_HrefList.Count <= 0 | 
|             || hrefIndex < 0) return; | 
|         if (hrefIndex < m_HrefList.Count) | 
|         { | 
|             m_HrefList[hrefIndex].Execute(eventIndex); | 
|         } | 
|     } | 
|     #endregion | 
|   | 
|     #region 自适应2 | 
|     /// <summary> | 
|     /// 牺牲了主动换行 | 
|     /// </summary> | 
|     private static StringBuilder textBuilder = new StringBuilder(); | 
|   | 
|     private Dictionary<int, Match> matchDics = new Dictionary<int, Match>(); | 
|   | 
|     private bool IsModifySize(int _index,out int _size) | 
|     { | 
|         _size = 0; | 
|         int _end = 0; | 
|         int _before = -1; | 
|         foreach (var _key in matchDics.Keys) | 
|         { | 
|             if (_index < _key) | 
|             { | 
|                 var _match = matchDics[_key]; | 
|                 if (WordAnalysis.Size_Start_Regex.IsMatch(_match.Value)) | 
|                 { | 
|                     break; | 
|                 } | 
|                 else if (WordAnalysis.Size_End_Regex.IsMatch(_match.Value)) | 
|                 { | 
|                     _end = _key; | 
|                     break; | 
|                 } | 
|             } | 
|         } | 
|         if (_end != 0) | 
|         { | 
|             foreach (var _key in matchDics.Keys) | 
|             { | 
|                 if (_key < _end) | 
|                 { | 
|                     var _match = matchDics[_key]; | 
|                     if (WordAnalysis.Size_Start_Regex.IsMatch(_match.Value)) | 
|                     { | 
|                         _before = _key; | 
|                     } | 
|                 } | 
|                 else | 
|                 { | 
|                     break; | 
|                 } | 
|             } | 
|         } | 
|         if (_before != -1) | 
|         { | 
|             _size = int.Parse(matchDics[_before].Groups[1].Value); | 
|             return true; | 
|         } | 
|         return false; | 
|     } | 
|   | 
|     public void SetFitterSize() | 
|     { | 
|         string fitterText = m_OutputText; | 
|         fitterText = fitterText.Replace("\n", ""); | 
|         float width = 0; | 
|   | 
|         textBuilder.Length = 0; | 
|         if (null == font && Application.isPlaying) | 
|         { | 
|             font = FontUtility.preferred; | 
|         } | 
|         var settings = GetGenerationSettings(Vector2.zero); | 
|   | 
|         float cache = 0; | 
|         string part = string.Empty; | 
|   | 
|         float ratio = GetResolutionRatio(); | 
|   | 
|         matchDics.Clear(); | 
|   | 
|         foreach (Match match in ImgAnalysis.Unity_Img_Regex.Matches(fitterText)) | 
|         { | 
|             if (!matchDics.ContainsKey(match.Index)) | 
|             { | 
|                 matchDics.Add(match.Index, match); | 
|             } | 
|         } | 
|   | 
|         foreach (Match match in WordAnalysis.Color_Start_Regex.Matches(fitterText)) | 
|         { | 
|             if (!matchDics.ContainsKey(match.Index)) | 
|             { | 
|                 matchDics.Add(match.Index, match); | 
|             } | 
|         } | 
|   | 
|         foreach (Match match in WordAnalysis.Color_End_Regex.Matches(fitterText)) | 
|         { | 
|             if (!matchDics.ContainsKey(match.Index)) | 
|             { | 
|                 matchDics.Add(match.Index, match); | 
|             } | 
|         } | 
|   | 
|         bool _modifySize = false; | 
|         foreach (Match match in WordAnalysis.Size_Start_Regex.Matches(fitterText)) | 
|         { | 
|             if (!matchDics.ContainsKey(match.Index)) | 
|             { | 
|                 _modifySize = true; | 
|                 matchDics.Add(match.Index, match); | 
|             } | 
|         } | 
|   | 
|         foreach (Match match in WordAnalysis.Size_End_Regex.Matches(fitterText)) | 
|         { | 
|             if (!matchDics.ContainsKey(match.Index)) | 
|             { | 
|                 matchDics.Add(match.Index, match); | 
|             } | 
|         } | 
|   | 
|         for (int i = 0; i < fitterText.Length; i++) | 
|         { | 
|             if (matchDics.ContainsKey(i)) | 
|             { | 
|                 Match match = matchDics[i]; | 
|                 if (ImgAnalysis.Unity_Img_Regex.IsMatch(match.Value)) | 
|                 { | 
|                     width += match.Length; | 
|                 } | 
|                 if (WordAnalysis.Color_Start_Regex.IsMatch(match.Value)) | 
|                 { | 
|                     textBuilder.Append(match.Value); | 
|                 } | 
|                 else if (WordAnalysis.Color_End_Regex.IsMatch(match.Value)) | 
|                 { | 
|                     textBuilder.Append(match.Value); | 
|                 } | 
|                 else if (WordAnalysis.Size_Start_Regex.IsMatch(match.Value)) | 
|                 { | 
|                     textBuilder.Append(match.Value); | 
|                 } | 
|                 else if (WordAnalysis.Size_End_Regex.IsMatch(match.Value)) | 
|                 { | 
|                     textBuilder.Append(match.Value); | 
|                 } | 
|                 else | 
|                 { | 
|                     cache = cachedTextGeneratorForLayout.GetPreferredWidth(match.Value, settings) * ratio; | 
|                     if (width + cache > (rectTransform.rect.width - 5)) | 
|                     { | 
|                         CacluHrefAndImgIndex(Mathf.Max(0, i - 1)); | 
|                         textBuilder.Append("\n"); | 
|                         width = cache; | 
|                     } | 
|                     else | 
|                     { | 
|                         width += cache; | 
|                     } | 
|                     textBuilder.Append(match.Value); | 
|                 } | 
|                 i += (match.Length - 1); | 
|             } | 
|             else | 
|             { | 
|                 var _size = 0; | 
|                 var _cacheFontSize = fontSize; | 
|                 if (_modifySize && IsModifySize(i, out _size)) | 
|                 { | 
|                     fontSize = _size; | 
|                     settings = GetGenerationSettings(Vector2.zero); | 
|                     cache = cachedTextGeneratorForLayout.GetPreferredWidth(fitterText[i].ToString(), settings) * ratio; | 
|                     fontSize = _cacheFontSize; | 
|                     settings = GetGenerationSettings(Vector2.zero); | 
|                 } | 
|                 else | 
|                 { | 
|                     cache = cachedTextGeneratorForLayout.GetPreferredWidth(fitterText[i].ToString(), settings) * ratio; | 
|                 } | 
|                 if (width + cache > (rectTransform.rect.width - 5)) | 
|                 { | 
|                     CacluHrefAndImgIndex(Mathf.Max(0, i - 1)); | 
|                     textBuilder.Append("\n"); | 
|                     width = cache; | 
|                 } | 
|                 else | 
|                 { | 
|                     width += cache; | 
|                 } | 
|                 textBuilder.Append(fitterText[i]); | 
|             } | 
|         } | 
|         CacluHrefAndImgIndex(); | 
|         m_OutputText = textBuilder.ToString(); | 
|     } | 
|   | 
|     private void CacluHrefAndImgIndex(int index) | 
|     { | 
|         for (int i = 0; i < m_ImgList.Count; i++) | 
|         { | 
|             if (index * 4 < m_ImgList[i].end) | 
|             { | 
|                 m_ImgList[i].cacheCnt += 1; | 
|             } | 
|         } | 
|   | 
|         for (int m = 0; m < m_HrefList.Count; m++) | 
|         { | 
|             RichTextMgr.HrefInfo hrefInfo = m_HrefList[m]; | 
|             if (index * 4 < hrefInfo.end) | 
|             { | 
|                 hrefInfo.end_cache_cnt += 1; | 
|             } | 
|             if (index * 4 < hrefInfo.start) | 
|             { | 
|                 hrefInfo.start_cache_cnt += 1; | 
|             } | 
|         } | 
|     } | 
|   | 
|     private void CacluHrefAndImgIndex() | 
|     { | 
|         for (int i = 0; i < m_ImgList.Count; i++) | 
|         { | 
|             m_ImgList[i].end += m_ImgList[i].cacheCnt * 4; | 
|         } | 
|   | 
|         for (int m = 0; m < m_HrefList.Count; m++) | 
|         { | 
|             RichTextMgr.HrefInfo hrefInfo = m_HrefList[m]; | 
|             hrefInfo.start += hrefInfo.start_cache_cnt * 4; | 
|             hrefInfo.end += hrefInfo.end_cache_cnt * 4; | 
|         } | 
|     } | 
|   | 
|     private float GetResolutionRatio() | 
|     { | 
|         return 1 / pixelsPerUnit; | 
|     } | 
|   | 
|     public override string text | 
|     { | 
|         get | 
|         { | 
|             return m_Text; | 
|         } | 
|         set | 
|         { | 
|             if (string.IsNullOrEmpty(value)) | 
|             { | 
|                 value = string.Empty; | 
|             } | 
|             m_RichText = value; | 
|             SetRichTextDirty(); | 
|         } | 
|     } | 
|   | 
| #if UNITY_EDITOR | 
|     protected override void OnValidate() | 
|     { | 
|         text = m_Text; | 
|     } | 
| #endif | 
|   | 
|     private void SetRichTextDirty() | 
|     { | 
|         m_RichText = UIHelper.ReplaceNewLine(m_RichText); | 
|         m_OutputText = GetOutputText(m_RichText); | 
|         if (AutoNewLine) | 
|         { | 
|             SetFitterSize(); | 
|         } | 
|         m_Text = m_OutputText; | 
|         SetVerticesDirty(); | 
|         SetLayoutDirty(); | 
|     } | 
|     #endregion | 
| } |