Beispiel #1
0
        /// <summary>
        /// Function to create a deep copy of a GlyphInfo.
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static GlyphInfo Clone (GlyphInfo source)
        {
            GlyphInfo copy = new GlyphInfo();

            copy.id = source.id;
            copy.x = source.x;
            copy.y = source.y;
            copy.width = source.width;
            copy.height = source.height;
            copy.xOffset = source.xOffset;
            copy.yOffset = source.yOffset;
            copy.xAdvance = source.xAdvance;

            return copy;
        }
Beispiel #2
0
        //private int loopCountB = 0;
        //private int loopCountC = 0;
        //private int loopCountD = 0;
        //private int loopCountE = 0;

       
        protected override void Awake()
        {
            //base.Awake();
            //Debug.Log("***** Awake() *****");

            m_isAwake = true;
            // Cache Reference to the Canvas
            m_canvas = GetComponentInParent(typeof(Canvas)) as Canvas;

            // Cache Reference to RectTransform.
            m_rectTransform = gameObject.GetComponent<RectTransform>();
            if (m_rectTransform == null)   
                m_rectTransform = gameObject.AddComponent<RectTransform>();
            

           
            // Cache a reference to the UIRenderer.
            m_uiRenderer = GetComponent<CanvasRenderer>();
            if (m_uiRenderer == null) 
                m_uiRenderer = gameObject.AddComponent<CanvasRenderer> ();

            if (m_mesh == null)
            {
                //Debug.Log("Creating new mesh.");
                m_mesh = new Mesh();
                m_mesh.hideFlags = HideFlags.HideAndDontSave;

                //m_mesh.bounds = new Bounds(transform.position, new Vector3(1000, 1000, 0));
            }

            // Cache reference to Mask Component if one is present
            //m_stencilID = MaterialManager.GetStencilID(gameObject);
            //m_mask = GetComponentInParent<Mask>();

            // Load TMP Settings
            if (m_settings == null) m_settings = TMP_Settings.LoadDefaultSettings();
            if (m_settings != null)
            {
                //m_enableWordWrapping = m_settings.enableWordWrapping;
                //m_enableKerning = m_settings.enableKerning;
                //m_enableExtraPadding = m_settings.enableExtraPadding;
            }

            // Load the font asset and assign material to renderer.
            LoadFontAsset();

            // Load Default TMP StyleSheet
            TMP_StyleSheet.LoadDefaultStyleSheet();

            // Allocate our initial buffers.
            m_char_buffer = new int[m_max_characters];
            m_cached_GlyphInfo = new GlyphInfo();
            m_isFirstAllocation = true;

            m_textInfo = new TMP_TextInfo();
            m_textInfo.meshInfo.mesh = m_mesh;


            // Check if we have a font asset assigned. Return if we don't because no one likes to see purple squares on screen.
            if (m_fontAsset == null)
            {
                Debug.LogWarning("Please assign a Font Asset to this " + transform.name + " gameobject.", this);
                return;
            }

            // Set Defaults for Font Auto-sizing
            if (m_fontSizeMin == 0) m_fontSizeMin = m_fontSize / 2;
            if (m_fontSizeMax == 0) m_fontSizeMax = m_fontSize * 2;

            //// Set flags to ensure our text is parsed and text re-drawn.
            isInputParsingRequired = true;
            m_havePropertiesChanged = true;
            m_rectTransformDimensionsChanged = true;

            ForceMeshUpdate(); // Added to force OnWillRenderObject() to be called in case object is not visible so we get initial bounds for the mesh.
        }
Beispiel #3
0
        /// <summary>
        /// This is the main function that is responsible for creating / displaying the text.
        /// </summary>
        void GenerateTextMesh()
        {
            //Debug.Log("***** GenerateTextMesh() ***** Frame: " + Time.frameCount); // + ". Point Size: " + m_fontSize + ". Margins are (W) " + m_marginWidth + "  (H) " + m_marginHeight); // ". Iteration Count: " + loopCountA + ".  Min: " + m_minFontSize + "  Max: " + m_maxFontSize + "  Delta: " + (m_maxFontSize - m_minFontSize) + "  Font size is " + m_fontSize); //called for Object with ID " + GetInstanceID()); // Assigned Material is " + m_uiRenderer.GetMaterial().name); // IncludeForMasking " + this.m_IncludeForMasking); // and text is " + m_text);
            //Debug.Log(this.defaultMaterial.GetInstanceID() + "  " + m_sharedMaterial.GetInstanceID() + "  " + m_uiRenderer.GetMaterial().GetInstanceID());
            
            // Early exit if no font asset was assigned. This should not be needed since Arial SDF will be assigned by default.
            if (m_fontAsset.characterDictionary == null)
            {
                Debug.Log("Can't Generate Mesh! No Font Asset has been assigned to Object ID: " + this.GetInstanceID());
                return;
            }

            // Reset TextInfo
            if (m_textInfo != null)
                m_textInfo.Clear();


            // Early exit if we don't have any Text to generate.
            if (m_char_buffer == null || m_char_buffer.Length == 0 || m_char_buffer[0] == (char)0)
            {
                //Debug.Log("Early Out! No Text has been set.");
                //Vector3[] vertices = m_textInfo.meshInfo.vertices;

                m_uiRenderer.SetMesh(null);

                if (m_inlineGraphics != null) m_inlineGraphics.ClearUIVertex();
                
                /*
                if (vertices != null)
                {
                    Array.Clear(vertices, 0, vertices.Length);
                    m_textInfo.meshInfo.mesh.vertices = vertices; 
                }
                */

                m_preferredWidth = 0;
                m_preferredHeight = 0;
                m_renderedWidth = 0;
                m_renderedHeight = 0;

                // This should only be called if there is a layout component attached
                LayoutRebuilder.MarkLayoutForRebuild(m_rectTransform);
                return;
            }

            m_currentFontAsset = m_fontAsset;
            m_currentMaterial = m_sharedMaterial;

            // Determine how many characters will be visible and make the necessary allocations (if needed).
            int totalCharacterCount = SetArraySizes(m_char_buffer);

            // Scale the font to approximately match the point size
            m_fontScale = (m_fontSize / m_currentFontAsset.fontInfo.PointSize);
            float baseScale = m_fontScale; // BaseScale keeps the character aligned vertically since <size=+000> results in font of different scale.
            m_maxFontScale = baseScale;
            float previousLineMaxScale = baseScale;
            float firstVisibleCharacterScale = 0;
            float spriteScale = 1;
            m_currentFontSize = m_fontSize;
            float fontSizeDelta = 0;

            int charCode = 0; // Holds the character code of the currently being processed character.
            //int prev_charCode = 0;
            bool isMissingCharacter; // Used to handle missing characters in the Font Atlas / Definition.

            m_style = m_fontStyle; // Set the default style.
            m_lineJustification = m_textAlignment; // Sets the line justification mode to match editor alignment.

            // GetPadding to adjust the size of the mesh due to border thickness, softness, glow, etc...
            if (checkPaddingRequired)
            {
                checkPaddingRequired = false;
                m_padding = ShaderUtilities.GetPadding(m_uiRenderer.GetMaterial(), m_enableExtraPadding, m_isUsingBold);
                //m_alignmentPadding = ShaderUtilities.GetFontExtent(m_sharedMaterial);
                m_isMaskingEnabled = ShaderUtilities.IsMaskingEnabled(m_sharedMaterial);
            }

            float style_padding = 0; // Extra padding required to accommodate Bold style.
            float xadvance_multiplier = 1; // Used to increase spacing between character when style is bold.

            m_baselineOffset = 0; // Used by subscript characters.

            // Underline
            bool beginUnderline = false;
            Vector3 underline_start = Vector3.zero; // Used to track where underline starts & ends.
            Vector3 underline_end = Vector3.zero;

            // Strike-through
            bool beginStrikethrough = false;
            Vector3 strikethrough_start = Vector3.zero;
            Vector3 strikethrough_end = Vector3.zero;

            m_fontColor32 = m_fontColor;
            Color32 vertexColor;
            m_htmlColor = m_fontColor32;
            m_colorStackIndex = 0;
            Array.Clear(m_colorStack, 0, m_colorStack.Length);

            m_styleStackIndex = 0;
            Array.Clear(m_styleStack, 0, m_styleStack.Length);

            m_lineOffset = 0; // Amount of space between lines (font line spacing + m_linespacing).
            m_lineHeight = 0;

            m_cSpacing = 0; // Amount of space added between characters as a result of the use of the <cspace> tag.
            m_monoSpacing = 0;
            float lineOffsetDelta = 0;
            m_xAdvance = 0; // Used to track the position of each character.
            m_maxXAdvance = 0;

            tag_LineIndent = 0; // Used for indentation of text.
            tag_Indent = 0;
            tag_NoParsing = false;
            m_isIgnoringAlignment = false;

            m_characterCount = 0; // Total characters in the char[]
            m_visibleCharacterCount = 0; // # of visible characters.
            m_visibleSpriteCount = 0;

            // Tracking of line information
            m_firstCharacterOfLine = 0;
            m_lastCharacterOfLine = 0;
            m_firstVisibleCharacterOfLine = 0;
            m_lastVisibleCharacterOfLine = 0;
            m_lineNumber = 0;
            bool isStartOfNewLine = true;

            m_pageNumber = 0;
            int pageToDisplay = Mathf.Clamp(m_pageToDisplay - 1, 0, m_textInfo.pageInfo.Length - 1);

            int ellipsisIndex = 0;

            m_rectTransform.GetLocalCorners(m_rectCorners);
            Vector4 margins = m_margin;
            float marginWidth = m_marginWidth;
            float marginHeight = m_marginHeight;
            m_marginLeft = 0;
            m_marginRight = 0;
            m_width = -1;
            
            // Used by Unity's Auto Layout system.
            m_renderedWidth = 0;
            m_renderedHeight = 0;

            // Initialize struct to track states of word wrapping
            bool isFirstWord = true;
            bool isLastBreakingChar = false;
            //bool isEastAsianLanguage = false;
            m_SavedLineState = new WordWrapState();
            m_SavedWordWrapState = new WordWrapState();
            int wrappingIndex = 0;

            // Need to initialize these Extents structures
            m_meshExtents = new Extents(k_InfinityVector, -k_InfinityVector);

            // Initialize lineInfo
            if (m_textInfo.lineInfo == null) m_textInfo.lineInfo = new TMP_LineInfo[2];
            for (int i = 0; i < m_textInfo.lineInfo.Length; i++)
            {
                m_textInfo.lineInfo[i] = new TMP_LineInfo();
                m_textInfo.lineInfo[i].lineExtents = new Extents(k_InfinityVector, -k_InfinityVector);
                m_textInfo.lineInfo[i].ascender = -k_InfinityVector.x;
                m_textInfo.lineInfo[i].descender = k_InfinityVector.x;
            }


            // Tracking of the highest Ascender
            m_maxAscender = 0;
            m_maxDescender = 0;
            float pageAscender = 0;
            float maxVisibleDescender = 0;
            bool isMaxVisibleDescenderSet = false;
            m_isNewPage = false;

            loopCountA += 1;

            int endTagIndex = 0;
            // Parse through Character buffer to read HTML tags and begin creating mesh.
            for (int i = 0; m_char_buffer[i] != 0; i++)
            {
                charCode = m_char_buffer[i];
                m_isSprite = false;
                spriteScale = 1;

                //Debug.Log("i:" + i + "  Character [" + (char)charCode + "] with ASCII of " + charCode);
                //if (m_characterCount >= m_maxVisibleCharacters || m_lineNumber >= m_maxVisibleLines)
                //    break;

                // Parse Rich Text Tag
                #region Parse Rich Text Tag
                if (m_isRichText && charCode == 60)  // '<'
                {
                    m_isParsingText = true;

                    // Check if Tag is valid. If valid, skip to the end of the validated tag.
                    if (ValidateHtmlTag(m_char_buffer, i + 1, out endTagIndex))
                    {
                        i = endTagIndex;

                        if (m_isRecalculateScaleRequired)
                        {
                            m_fontScale = m_currentFontSize / m_currentFontAsset.fontInfo.PointSize;
                            m_isRecalculateScaleRequired = false;
                        }

                        if (!m_isSprite)
                            continue;
                    }
                }
                #endregion End Parse Rich Text Tag

                m_isParsingText = false;
                isMissingCharacter = false;

                // Check if we should be using a different font asset
                //if (m_fontIndex != 0)
                //{
                //    // Check if we need to load the new font asset
                //    if (m_currentFontAsset == null)
                //    {
                //        Debug.Log("Loading secondary font asset.");
                //        m_currentFontAsset = Resources.Load("Fonts & Materials/Bangers SDF", typeof(TextMeshProFont)) as TextMeshProFont;
                //        //m_sharedMaterials.Add(m_currentFontAsset.material);
                //        //m_renderer.sharedMaterials = new Material[] { m_sharedMaterial, m_currentFontAsset.material }; // m_sharedMaterials.ToArray();
                //    }
                //}               
                //Debug.Log("Char [" + (char)charCode + "] is using FontIndex: " + m_fontIndex);



                // Handle Font Styles like LowerCase, UpperCase and SmallCaps.
                #region Handling of LowerCase, UpperCase and SmallCaps Font Styles
                if ((m_style & FontStyles.UpperCase) == FontStyles.UpperCase)
                {
                    // If this character is lowercase, switch to uppercase.
                    if (char.IsLower((char)charCode))
                        charCode = char.ToUpper((char)charCode);

                }
                else if ((m_style & FontStyles.LowerCase) == FontStyles.LowerCase)
                {
                    // If this character is uppercase, switch to lowercase.
                    if (char.IsUpper((char)charCode))
                        charCode = char.ToLower((char)charCode);
                }
                else if ((m_fontStyle & FontStyles.SmallCaps) == FontStyles.SmallCaps || (m_style & FontStyles.SmallCaps) == FontStyles.SmallCaps)
                {
                    if (char.IsLower((char)charCode))
                    {
                        m_fontScale = m_currentFontSize * 0.8f / m_currentFontAsset.fontInfo.PointSize;
                        charCode = char.ToUpper((char)charCode);
                    }
                    else
                        m_fontScale = m_currentFontSize / m_currentFontAsset.fontInfo.PointSize;

                }
                #endregion


                // Look up Character Data from Dictionary and cache it.
                #region Look up Character Data
                if (m_isSprite)
                {
                    SpriteInfo spriteInfo = m_inlineGraphics.GetSprite(m_spriteIndex);
                    if (spriteInfo == null) continue;

                    // Sprites are assigned in the E000 Private Area + sprite Index
                    charCode = 57344 + m_spriteIndex;

                    m_cached_GlyphInfo = new GlyphInfo(); // Generates 40 bytes

                    m_cached_GlyphInfo.x = spriteInfo.x;
                    m_cached_GlyphInfo.y = spriteInfo.y;
                    m_cached_GlyphInfo.width = spriteInfo.width;
                    m_cached_GlyphInfo.height = spriteInfo.height;
                    m_cached_GlyphInfo.xOffset = spriteInfo.pivot.x + spriteInfo.xOffset;
                    m_cached_GlyphInfo.yOffset = spriteInfo.pivot.y + spriteInfo.yOffset;

                    spriteScale = m_fontAsset.fontInfo.Ascender / spriteInfo.height * spriteInfo.scale;
                   
                    m_cached_GlyphInfo.xAdvance = spriteInfo.xAdvance * spriteScale;

                    m_textInfo.characterInfo[m_characterCount].type = TMP_CharacterType.Sprite;
                }
                else
                {
                    m_currentFontAsset.characterDictionary.TryGetValue(charCode, out m_cached_GlyphInfo);
                    if (m_cached_GlyphInfo == null)
                    {
                        // Character wasn't found in the Dictionary.

                        if (char.IsLower((char)charCode))
                        {
                            if (m_currentFontAsset.characterDictionary.TryGetValue(char.ToUpper((char)charCode), out m_cached_GlyphInfo))
                                charCode = char.ToUpper((char)charCode);
                        }
                        else if (char.IsUpper((char)charCode))
                        {
                            if (m_currentFontAsset.characterDictionary.TryGetValue(char.ToLower((char)charCode), out m_cached_GlyphInfo))
                                charCode = char.ToLower((char)charCode);
                        }

                        // Still don't have a replacement?
                        if (m_cached_GlyphInfo == null)
                        {
                            m_currentFontAsset.characterDictionary.TryGetValue(88, out m_cached_GlyphInfo);
                            if (m_cached_GlyphInfo != null)
                            {
                                Debug.LogWarning("Character with ASCII value of " + charCode + " was not found in the Font Asset Glyph Table.", this);
                                // Replace the missing character by X (if it is found)
                                charCode = 88;
                                isMissingCharacter = true;
                            }
                            else
                            {  // At this point the character isn't in the Dictionary, the replacement X isn't either so ...
                                Debug.LogWarning("Character with ASCII value of " + charCode + " was not found in the Font Asset Glyph Table.", this);
                                continue;
                            }
                        }
                    }

                    m_textInfo.characterInfo[m_characterCount].type = TMP_CharacterType.Character;
                }
                #endregion

                // Store some of the text object's information
                m_textInfo.characterInfo[m_characterCount].character = (char)charCode;
                m_textInfo.characterInfo[m_characterCount].pointSize = m_currentFontSize;
                m_textInfo.characterInfo[m_characterCount].color = m_htmlColor;
                m_textInfo.characterInfo[m_characterCount].style = m_style;
                m_textInfo.characterInfo[m_characterCount].index = (short)i;
                //m_textInfo.characterInfo[m_characterCount].isIgnoringAlignment = m_isIgnoringAlignment;


                // Handle Kerning if Enabled.
                #region Handle Kerning
                if (m_enableKerning && m_characterCount >= 1)
                {
                    int prev_charCode = m_textInfo.characterInfo[m_characterCount - 1].character;
                    KerningPairKey keyValue = new KerningPairKey(prev_charCode, charCode);

                    KerningPair pair;

                    m_currentFontAsset.kerningDictionary.TryGetValue(keyValue.key, out pair);
                    if (pair != null)
                    {
                        m_xAdvance += pair.XadvanceOffset * m_fontScale;
                    }
                }
                #endregion


                // Handle Mono Spacing
                #region Handle Mono Spacing
                float monoAdvance = 0;
                if (m_monoSpacing != 0)
                {
                    monoAdvance = (m_monoSpacing / 2 - (m_cached_GlyphInfo.width / 2 + m_cached_GlyphInfo.xOffset) * m_fontScale) * (1 - m_charWidthAdjDelta);
                    m_xAdvance += monoAdvance;
                }
                #endregion


                // Set Padding based on selected font style
                #region Handle Style Padding
                if ((m_style & FontStyles.Bold) == FontStyles.Bold || (m_fontStyle & FontStyles.Bold) == FontStyles.Bold) // Checks for any combination of Bold Style.
                {
                    style_padding = m_currentFontAsset.BoldStyle * 2;
                    xadvance_multiplier = 1 + m_currentFontAsset.boldSpacing * 0.01f;
                }
                else
                {
                    style_padding = m_currentFontAsset.NormalStyle * 2;
                    xadvance_multiplier = 1.0f;
                }
                #endregion Handle Style Padding


                // Set padding value if Character or Sprite
                float padding = m_isSprite ? 0 : m_padding;

                // Determine the position of the vertices of the Character or Sprite.
                Vector3 top_left = new Vector3(0 + m_xAdvance + ((m_cached_GlyphInfo.xOffset - padding - style_padding) * m_fontScale * spriteScale * (1 - m_charWidthAdjDelta)), (m_cached_GlyphInfo.yOffset + padding) * m_fontScale * spriteScale - m_lineOffset + m_baselineOffset, 0);
                Vector3 bottom_left = new Vector3(top_left.x, top_left.y - ((m_cached_GlyphInfo.height + padding * 2) * m_fontScale * spriteScale), 0);
                Vector3 top_right = new Vector3(bottom_left.x + ((m_cached_GlyphInfo.width + padding * 2 + style_padding * 2) * m_fontScale * spriteScale * (1 - m_charWidthAdjDelta)), top_left.y, 0);
                Vector3 bottom_right = new Vector3(top_right.x, bottom_left.y, 0);

                // Check if we need to Shear the rectangles for Italic styles
                #region Handle Italic & Shearing
                if ((m_style & FontStyles.Italic) == FontStyles.Italic || (m_fontStyle & FontStyles.Italic) == FontStyles.Italic)
                {
                    // Shift Top vertices forward by half (Shear Value * height of character) and Bottom vertices back by same amount. 
                    float shear_value = m_currentFontAsset.ItalicStyle * 0.01f;
                    Vector3 topShear = new Vector3(shear_value * ((m_cached_GlyphInfo.yOffset + padding + style_padding) * m_fontScale * spriteScale), 0, 0);
                    Vector3 bottomShear = new Vector3(shear_value * (((m_cached_GlyphInfo.yOffset - m_cached_GlyphInfo.height - padding - style_padding)) * m_fontScale * spriteScale), 0, 0);

                    top_left = top_left + topShear;
                    bottom_left = bottom_left + bottomShear;
                    top_right = top_right + topShear;
                    bottom_right = bottom_right + bottomShear;
                }
                #endregion Handle Italics & Shearing


                // Store position of the vertices for the Character or Sprite.
                m_textInfo.characterInfo[m_characterCount].bottomLeft = bottom_left;
                m_textInfo.characterInfo[m_characterCount].topLeft = top_left;
                m_textInfo.characterInfo[m_characterCount].topRight = top_right;
                m_textInfo.characterInfo[m_characterCount].bottomRight = bottom_right;
                m_textInfo.characterInfo[m_characterCount].baseLine = 0 - m_lineOffset + m_baselineOffset;
                m_textInfo.characterInfo[m_characterCount].scale = m_fontScale;


                // Compute MaxAscender & MaxDescender which is used for AutoScaling & other type layout options
                float ascender = m_fontAsset.fontInfo.Ascender * m_fontScale + m_baselineOffset;
                if ((charCode == 10 || charCode == 13) && m_characterCount > m_firstVisibleCharacterOfLine)
                    ascender = m_baselineOffset;

                float descender = m_fontAsset.fontInfo.Descender * m_fontScale - m_lineOffset + m_baselineOffset;

                // Check if Sprite exceeds the Ascender and Descender of the font and if so make the adjustment.
                if (m_isSprite)
                {
                    ascender = Mathf.Max(ascender, top_left.y - padding * m_fontScale * spriteScale);
                    descender = Mathf.Min(descender, bottom_right.y - padding * m_fontScale * spriteScale);
                }

                if (m_lineNumber == 0) m_maxAscender = m_maxAscender > ascender ? m_maxAscender : ascender;
                if (m_lineOffset == 0) pageAscender = pageAscender > ascender ? pageAscender : ascender;

                // Track Line Height
                //maxLineHeight = Mathf.Max(m_lineHeight, maxLineHeight);

                // Used to adjust line spacing when larger fonts or the size tag is used.
                if (m_baselineOffset == 0)
                    m_maxFontScale = Mathf.Max(m_maxFontScale, m_fontScale);

                // Set Characters to not visible by default.
                m_textInfo.characterInfo[m_characterCount].isVisible = false;


                // Setup Mesh for visible characters or sprites. ie. not a SPACE / LINEFEED / CARRIAGE RETURN.
                #region Handle Visible Characters
                if (charCode != 10 && charCode != 13 && charCode != 32 && charCode != 160 || m_isSprite)
                {
                    m_textInfo.characterInfo[m_characterCount].isVisible = true;
                    //if (isStartOfNewLine) { isStartOfNewLine = false; m_firstVisibleCharacterOfLine = m_characterCount; }

                    // Check if Character exceeds the width of the Text Container
                    #region Check for Characters Exceeding Width of Text Container
                    float width = m_width != -1 ? Mathf.Min(marginWidth + 0.0001f - m_marginLeft - m_marginRight, m_width) : marginWidth + 0.0001f - m_marginLeft - m_marginRight;

                    m_textInfo.lineInfo[m_lineNumber].width = width;
                    m_textInfo.lineInfo[m_lineNumber].marginLeft = m_marginLeft;

                    if (m_xAdvance + m_cached_GlyphInfo.xAdvance * (1 - m_charWidthAdjDelta) * m_fontScale > width)
                    {
                        ellipsisIndex = m_characterCount - 1; // Last safely rendered character

                        // Word Wrapping
                        #region Handle Word Wrapping
                        if (enableWordWrapping && m_characterCount != m_firstCharacterOfLine)
                        {

                            if (wrappingIndex == m_SavedWordWrapState.previous_WordBreak || isFirstWord)
                            {
                                // Word wrapping is no longer possible. Shrink size of text if auto-sizing is enabled.
                                if (m_enableAutoSizing && m_fontSize > m_fontSizeMin)
                                {

                                    // Handle Character Width Adjustments
                                    #region Character Width Adjustments
                                    if (m_charWidthAdjDelta < m_charWidthMaxAdj / 100)
                                    {
                                        loopCountA = 0;
                                        m_charWidthAdjDelta += 0.01f;
                                        GenerateTextMesh();
                                        return;
                                    }
                                    #endregion
 
                                    // Adjust Point Size 
                                    m_maxFontSize = m_fontSize;

                                    m_fontSize -= Mathf.Max((m_fontSize - m_minFontSize) / 2, 0.05f);
                                    m_fontSize = (int)(Mathf.Max(m_fontSize, m_fontSizeMin) * 20 + 0.5f) / 20f;

                                    if (loopCountA > 20) return; // Added to debug
                                    GenerateTextMesh();
                                    return;
                                }

                                // Word wrapping is no longer possible, now breaking up individual words.
                                if (m_isCharacterWrappingEnabled == false)
                                {
                                    m_isCharacterWrappingEnabled = true;
                                }
                                else
                                    isLastBreakingChar = true;

                                //Debug.Log("Wrapping Index " + wrappingIndex + ". Recursive Count: " + m_recursiveCount);

                                m_recursiveCount += 1;
                                if (m_recursiveCount > 20)
                                {
                                    //Debug.Log("Recursive count exceeded!");
                                    continue;
                                }

                                //Debug.Log("Line #" + m_lineNumber + " Character [" + (char)charCode + "] cannot be wrapped.  WrappingIndex: " + wrappingIndex + "  Saved Index: " + m_SavedWordWrapState.previous_WordBreak + ". Character Count is " + m_characterCount);
                            }


                            // Restore to previously stored state of last valid (space character or linefeed)
                            i = RestoreWordWrappingState(ref m_SavedWordWrapState);
                            wrappingIndex = i;  // Used to detect when line length can no longer be reduced.

                            //Debug.Log("Last Visible Character of line # " + m_lineNumber + " is [" + m_textInfo.characterInfo[m_lastVisibleCharacterOfLine].character + " Character Count: " + m_characterCount + " Last visible: " + m_lastVisibleCharacterOfLine);

                            // Check if Line Spacing of previous line needs to be adjusted.
                            FaceInfo face = m_currentFontAsset.fontInfo;
                            float gap = m_lineHeight == 0 ? face.LineHeight - (face.Ascender - face.Descender) : m_lineHeight - (face.Ascender - face.Descender);
                            if (m_lineNumber > 0 && m_maxFontScale != 0 && m_lineHeight == 0 && firstVisibleCharacterScale != m_maxFontScale && !m_isNewPage)
                            {
                                float offsetDelta = 0 - face.Descender * previousLineMaxScale + (face.Ascender + gap + m_lineSpacing + m_paragraphSpacing + m_lineSpacingDelta) * m_maxFontScale;
                                m_lineOffset += offsetDelta - lineOffsetDelta;
                                AdjustLineOffset(m_firstCharacterOfLine, m_characterCount - 1, offsetDelta - lineOffsetDelta);
                                m_SavedWordWrapState.lineOffset = m_lineOffset;
                            }
                            m_isNewPage = false;


                            // Calculate lineAscender & make sure if last character is superscript or subscript that we check that as well.
                            float lineAscender = m_fontAsset.fontInfo.Ascender * m_maxFontScale - m_lineOffset;
                            float lineAscender2 = m_fontAsset.fontInfo.Ascender * m_fontScale - m_lineOffset + m_baselineOffset;
                            lineAscender = lineAscender > lineAscender2 ? lineAscender : lineAscender2;

                            // Calculate lineDescender & make sure if last character is superscript or subscript that we check that as well.
                            float lineDescender = m_fontAsset.fontInfo.Descender * m_maxFontScale - m_lineOffset;
                            float lineDescender2 = m_fontAsset.fontInfo.Descender * m_fontScale - m_lineOffset + m_baselineOffset;
                            lineDescender = lineDescender < lineDescender2 ? lineDescender : lineDescender2;

                            // Update maxDescender and maxVisibleDescender
                            m_maxDescender = m_maxDescender < lineDescender ? m_maxDescender : lineDescender;
                            if (!isMaxVisibleDescenderSet)
                                maxVisibleDescender = m_maxDescender;

                            if (m_characterCount >= m_maxVisibleCharacters || m_lineNumber >= m_maxVisibleLines)
                                isMaxVisibleDescenderSet = true;

                            // Track & Store lineInfo for the new line
                            m_textInfo.lineInfo[m_lineNumber].firstCharacterIndex = m_firstCharacterOfLine;
                            m_textInfo.lineInfo[m_lineNumber].firstVisibleCharacterIndex = m_firstVisibleCharacterOfLine;
                            m_textInfo.lineInfo[m_lineNumber].lastCharacterIndex = m_characterCount - 1 > 0 ? m_characterCount - 1 : 0;
                            m_textInfo.lineInfo[m_lineNumber].lastVisibleCharacterIndex = m_lastVisibleCharacterOfLine;
                            m_textInfo.lineInfo[m_lineNumber].characterCount = m_textInfo.lineInfo[m_lineNumber].lastCharacterIndex - m_textInfo.lineInfo[m_lineNumber].firstCharacterIndex + 1;

                            m_textInfo.lineInfo[m_lineNumber].lineExtents.min = new Vector2(m_textInfo.characterInfo[m_firstVisibleCharacterOfLine].bottomLeft.x, lineDescender);
                            m_textInfo.lineInfo[m_lineNumber].lineExtents.max = new Vector2(m_textInfo.characterInfo[m_lastVisibleCharacterOfLine].topRight.x, lineAscender);
                            m_textInfo.lineInfo[m_lineNumber].lineLength = m_textInfo.lineInfo[m_lineNumber].lineExtents.max.x - padding * m_maxFontScale;
                            m_textInfo.lineInfo[m_lineNumber].maxAdvance = m_textInfo.characterInfo[m_lastVisibleCharacterOfLine].xAdvance - m_characterSpacing * m_fontScale;
                            m_textInfo.lineInfo[m_lineNumber].maxScale = m_maxFontScale;

                            m_firstCharacterOfLine = m_characterCount; // Store first character of the next line.

                            // Compute Preferred Width & Height
                            m_renderedWidth += m_xAdvance;
                            if (m_enableWordWrapping)
                                m_renderedHeight = m_maxAscender - m_maxDescender;
                            else
                                m_renderedHeight = Mathf.Max(m_renderedHeight, lineAscender - lineDescender);

                            //Debug.Log("Line # " + m_lineNumber + "  Max Font Scale: " + m_maxFontScale + "  Current Font Scale: " + currentFontScale);
                            //Debug.Log("LineInfo for line # " + (m_lineNumber) + " First character [" + m_textInfo.characterInfo[m_textInfo.lineInfo[m_lineNumber].firstCharacterIndex].character + "] at Index: " + m_textInfo.lineInfo[m_lineNumber].firstCharacterIndex +
                            //                                                    " First visible character [" + m_textInfo.characterInfo[m_textInfo.lineInfo[m_lineNumber].firstVisibleCharacterIndex].character + "] at Index: " + m_textInfo.lineInfo[m_lineNumber].firstVisibleCharacterIndex +
                            //                                                    " Last character [" + m_textInfo.characterInfo[m_textInfo.lineInfo[m_lineNumber].lastCharacterIndex].character + "] at index: " + m_textInfo.lineInfo[m_lineNumber].lastCharacterIndex +
                            //                                                    " Last Visible character [" + m_textInfo.characterInfo[m_textInfo.lineInfo[m_lineNumber].lastVisibleCharacterIndex].character + "] at index: " + m_textInfo.lineInfo[m_lineNumber].lastVisibleCharacterIndex +
                            //                                                    " Character Count of " + m_textInfo.lineInfo[m_lineNumber].characterCount /* + " Line Length of " + m_textInfo.lineInfo[m_lineNumber].lineLength +
                            //                                                    "  MinX: " + m_textInfo.lineInfo[m_lineNumber].lineExtents.min.x + "  MinY: " + m_textInfo.lineInfo[m_lineNumber].lineExtents.min.y +
                            //                                                    "  MaxX: " + m_textInfo.lineInfo[m_lineNumber].lineExtents.max.x + "  MaxY: " + m_textInfo.lineInfo[m_lineNumber].lineExtents.max.y +
                            //                                                    "  Line Ascender: " + lineAscender + "  Line Descender: " + lineDescender */ );

                            // Store the state of the line before starting on the new line.
                            SaveWordWrappingState(ref m_SavedLineState, i, m_characterCount - 1);

                            m_lineNumber += 1;
                            isStartOfNewLine = true;

                            // Check to make sure Array is large enough to hold a new line.
                            if (m_lineNumber >= m_textInfo.lineInfo.Length)
                                ResizeLineExtents(m_lineNumber);

                            // Apply Line Spacing based on scale of the last character of the line.
                            FontStyles style = m_textInfo.characterInfo[m_characterCount].style;
                            float scale = (style & FontStyles.Subscript) == FontStyles.Subscript || (style & FontStyles.Superscript) == FontStyles.Superscript ? m_maxFontScale : m_textInfo.characterInfo[m_characterCount].scale;
                            lineOffsetDelta = 0 - face.Descender * m_maxFontScale + (face.Ascender + gap + m_lineSpacing + m_lineSpacingDelta) * scale;
                            m_lineOffset += lineOffsetDelta;


                            previousLineMaxScale = m_maxFontScale;
                            firstVisibleCharacterScale = scale;
                            m_maxFontScale = 0;
                            spriteScale = 1;
                            m_xAdvance = 0 + tag_Indent;

                            continue;
                        }
                        #endregion End Word Wrapping


                        // Text Auto-Sizing (text exceeding Width of container. 
                        #region Handle Text Auto-Sizing
                        if (m_enableAutoSizing && m_fontSize > m_fontSizeMin)
                        {
                            // Handle Character Width Adjustments
                            #region Character Width Adjustments
                            if (m_charWidthAdjDelta < m_charWidthMaxAdj / 100)
                            {
                                loopCountA = 0;
                                m_charWidthAdjDelta += 0.01f;
                                GenerateTextMesh();
                                return;
                            }
                            #endregion

                            // Adjust Point Size
                            m_maxFontSize = m_fontSize;

                            m_fontSize -= Mathf.Max((m_fontSize - m_minFontSize) / 2, 0.05f);
                            m_fontSize = (int)(Mathf.Max(m_fontSize, m_fontSizeMin) * 20 + 0.5f) / 20f;

                            m_recursiveCount = 0;
                            if (loopCountA > 20) return; // Added to debug 
                            GenerateTextMesh();
                            return;
                        }
                        #endregion End Text Auto-Sizing


                        // Handle Text Overflow
                        #region Handle Text Overflow
                        switch (m_overflowMode)
                        {
                            case TextOverflowModes.Overflow:
                                if (m_isMaskingEnabled)
                                    DisableMasking();

                                break;
                            case TextOverflowModes.Ellipsis:
                                if (m_isMaskingEnabled)
                                    DisableMasking();

                                m_isTextTruncated = true;

                                if (m_characterCount < 1)
                                {
                                    m_textInfo.characterInfo[m_characterCount].isVisible = false;
                                    m_visibleCharacterCount -= 1;
                                    break;
                                }

                                m_char_buffer[i - 1] = 8230;
                                m_char_buffer[i] = (char)0;

                                GenerateTextMesh();
                                return;
                            case TextOverflowModes.Masking:
                                if (!m_isMaskingEnabled)
                                    EnableMasking();
                                break;
                            case TextOverflowModes.ScrollRect:
                                if (!m_isMaskingEnabled)
                                    EnableMasking();
                                break;
                            case TextOverflowModes.Truncate:
                                if (m_isMaskingEnabled)
                                    DisableMasking();

                                m_textInfo.characterInfo[m_characterCount].isVisible = false;
                                break;
                        }
                        #endregion End Text Overflow

                    }
                    #endregion End Check for Characters Exceeding Width of Text Container

                    if (charCode != 9)
                    {
                        // Determine Vertex Color
                        if (isMissingCharacter)
                            vertexColor = Color.red;
                        else if (m_overrideHtmlColors)
                            vertexColor = m_fontColor32;
                        else
                            vertexColor = m_htmlColor;


                        // Store Character & Sprite Vertex Information
                        if (!m_isSprite)
                            SaveGlyphVertexInfo(style_padding, vertexColor);
                        else
                            SaveSpriteVertexInfo(vertexColor);
                    }
                    else // If character is Tab
                    {
                        m_textInfo.characterInfo[m_characterCount].isVisible = false;
                        m_lastVisibleCharacterOfLine = m_characterCount;
                        m_textInfo.lineInfo[m_lineNumber].spaceCount += 1;
                        m_textInfo.spaceCount += 1;
                    }

                    // Increase visible count for Characters.
                    if (m_textInfo.characterInfo[m_characterCount].isVisible)
                    {
                        if (m_isSprite)
                            m_visibleSpriteCount += 1;
                        else
                            m_visibleCharacterCount += 1;

                        if (isStartOfNewLine) { isStartOfNewLine = false; m_firstVisibleCharacterOfLine = m_characterCount; }
                        m_lastVisibleCharacterOfLine = m_characterCount;
                    }

                }
                else
                {   // This is a Space, Tab, LineFeed or Carriage Return

                    // Track # of spaces per line which is used for line justification.
                    if (charCode == 9 || charCode == 32 || charCode == 160)
                    {
                        m_textInfo.lineInfo[m_lineNumber].spaceCount += 1;
                        m_textInfo.spaceCount += 1;
                    }
                }
                #endregion Handle Visible Characters


                // Store Rectangle positions for each Character.
                #region Store Character Data
                m_textInfo.characterInfo[m_characterCount].lineNumber = (short)m_lineNumber;
                m_textInfo.characterInfo[m_characterCount].pageNumber = (short)m_pageNumber;

                if (charCode != 10 && charCode != 13 && charCode != 8230 || m_textInfo.lineInfo[m_lineNumber].characterCount == 1)
                    m_textInfo.lineInfo[m_lineNumber].alignment = m_lineJustification;
                #endregion Store Character Data


                // Check if text Exceeds the vertical bounds of the margin area.
                #region Check Vertical Bounds & Auto-Sizing
                if (m_maxAscender - descender > marginHeight + 0.0001f)
                {
                    //Debug.Log((m_maxAscender - descender + (m_alignmentPadding.w * 2 * m_fontScale)).ToString("f6") + "  " + marginHeight.ToString("f6"));
                    //Debug.Log("Character [" + (char)charCode + "] at Index: " + m_characterCount + " has exceeded the Height of the text container. Max Ascender: " + m_maxAscender + "  Max Descender: " + m_maxDescender + "  Margin Height: " + marginHeight + " Bottom Left: " + bottom_left.y);                                              

                    // Handle Line spacing adjustments
                    #region Line Spacing Adjustments
                    if (m_enableAutoSizing && m_lineSpacingDelta > m_lineSpacingMax && m_lineNumber > 0)
                    {
                        m_lineSpacingDelta -= 1;
                        GenerateTextMesh();
                        return;
                    }
                    #endregion


                    // Handle Text Auto-sizing resulting from text exceeding vertical bounds.
                    #region Text Auto-Sizing (Text greater than vertical bounds)
                    if (m_enableAutoSizing && m_fontSize > m_fontSizeMin)
                    {
                        m_maxFontSize = m_fontSize;

                        m_fontSize -= Mathf.Max((m_fontSize - m_minFontSize) / 2, 0.05f);
                        m_fontSize = (int)(Mathf.Max(m_fontSize, m_fontSizeMin) * 20 + 0.5f) / 20f;

                        m_recursiveCount = 0;
                        if (loopCountA > 20) return; // Added to debug 
                        GenerateTextMesh();
                        return;
                    }
                    #endregion Text Auto-Sizing


                    // Handle Text Overflow
                    #region Text Overflow
                    switch (m_overflowMode)
                    {
                        case TextOverflowModes.Overflow:
                            if (m_isMaskingEnabled)
                                DisableMasking();

                            break;
                        case TextOverflowModes.Ellipsis:
                            if (m_isMaskingEnabled)
                                DisableMasking();

                            if (m_lineNumber > 0)
                            {
                                m_char_buffer[m_textInfo.characterInfo[ellipsisIndex].index] = 8230;
                                m_char_buffer[m_textInfo.characterInfo[ellipsisIndex].index + 1] = (char)0;
                                GenerateTextMesh();
                                m_isTextTruncated = true;
                                return;
                            }
                            else
                            {
                                m_char_buffer[0] = (char)0;
                                GenerateTextMesh();
                                m_isTextTruncated = true;
                                return;
                            }
                        case TextOverflowModes.Masking:
                            if (!m_isMaskingEnabled)
                                EnableMasking();
                            break;
                        case TextOverflowModes.ScrollRect:
                            if (!m_isMaskingEnabled)
                                EnableMasking();
                            break;
                        case TextOverflowModes.Truncate:
                         if (m_isMaskingEnabled)
                                DisableMasking();
                    
                            // Alternative Implementation 
                            //if (m_lineNumber > 0)
                            //{
                            //    if (!m_isTextTruncated && m_textInfo.characterInfo[ellipsisIndex + 1].character != 10)
                            //    {
                            //        Debug.Log("Char [" + (char)charCode + "] on line " + m_lineNumber + " exceeds the vertical bounds. Last safe character was " + (int)m_textInfo.characterInfo[ellipsisIndex + 1].character);
                            //        i = RestoreWordWrappingState(ref m_SavedWordWrapState);
                            //        m_lineNumber -= 1;
                            //        m_isTextTruncated = true;
                            //        m_isCharacterWrappingEnabled = true;
                            //        continue;
                            //    }
                            //    else
                            //    {
                            //        //Debug.Log("Char [" + (char)charCode + "] on line " + m_lineNumber + " set to invisible.");
                            //        m_textInfo.characterInfo[m_characterCount].isVisible = false;
                            //    }
                            ////    m_char_buffer[m_textInfo.characterInfo[ellipsisIndex].index + 1] = (char)0;
                            ////    m_isTextTruncated = true;
                            ////    i = RestoreWordWrappingState(ref m_SavedLineState);
                            ////    m_lineNumber -= 1;
                            
                            ////    continue;
                            //}
                            //break;

                            
                            // TODO : Optimize 
                            if (m_lineNumber > 0)
                            {
                                m_char_buffer[m_textInfo.characterInfo[ellipsisIndex].index + 1] = (char)0;
                                GenerateTextMesh();
                                m_isTextTruncated = true;
                                return;
                            }
                            else
                            {
                                m_char_buffer[0] = (char)0;
                                GenerateTextMesh();
                                m_isTextTruncated = true;
                                return;
                            }
                        case TextOverflowModes.Page:
                            if (m_isMaskingEnabled)
                                DisableMasking();

                            // Ignore Page Break, Linefeed or carriage return
                            if (charCode == 13 || charCode == 10)
                                break;

                            //Debug.Log("Character is [" + (char)charCode + "] with ASCII (" + charCode + ") on Page " + m_pageNumber + ". Ascender: " + m_textInfo.pageInfo[m_pageNumber].ascender + "  BaseLine: " + m_textInfo.pageInfo[m_pageNumber].baseLine + "  Descender: " + m_textInfo.pageInfo[m_pageNumber].descender);                          

                            // Go back to previous line and re-layout 
                            i = RestoreWordWrappingState(ref m_SavedLineState);
                            if (i == 0)
                            {
                                m_char_buffer[0] = (char)0;
                                GenerateTextMesh();
                                m_isTextTruncated = true;
                                return;
                            }

                            m_isNewPage = true;
                            m_xAdvance = 0 + tag_Indent;
                            m_lineOffset = 0;
                            m_lineNumber += 1;
                            m_pageNumber += 1;
                            continue;
                    }
                    #endregion End Text Overflow

                }
                #endregion Check Vertical Bounds


                // Handle xAdvance & Tabulation Stops. Tab stops at every 25% of Font Size.
                #region XAdvance, Tabulation & Stops
                if (charCode == 9)
                    m_xAdvance += m_fontAsset.fontInfo.TabWidth * m_fontScale;
                else if (m_monoSpacing != 0)
                    m_xAdvance += (m_monoSpacing - monoAdvance + (m_characterSpacing * m_fontScale) + m_cSpacing) * (1 - m_charWidthAdjDelta);
                else
                    m_xAdvance += ((m_cached_GlyphInfo.xAdvance * xadvance_multiplier + m_characterSpacing) * m_fontScale + m_cSpacing) * (1 - m_charWidthAdjDelta);


                // Store xAdvance information
                m_textInfo.characterInfo[m_characterCount].xAdvance = m_xAdvance;

                #endregion Tabulation & Stops


                // Handle Carriage Return
                #region Carriage Return
                if (charCode == 13)
                {
                    m_maxXAdvance = Mathf.Max(m_maxXAdvance, m_renderedWidth + m_xAdvance);
                    m_renderedWidth = 0;
                    m_xAdvance = 0 + tag_Indent;
                }
                #endregion Carriage Return


                // Handle Line Spacing Adjustments + Word Wrapping & special case for last line.
                #region Check for Line Feed and Last Character
                if (charCode == 10 || m_characterCount == totalCharacterCount - 1)
                {
                    // Check if Line Spacing of previous line needs to be adjusted.
                    FaceInfo face = m_currentFontAsset.fontInfo;
                    float gap = m_lineHeight == 0 ? face.LineHeight - (face.Ascender - face.Descender) : m_lineHeight - (face.Ascender - face.Descender);
                    if (m_lineNumber > 0 && m_maxFontScale != 0 && m_lineHeight == 0 && firstVisibleCharacterScale != m_maxFontScale && !m_isNewPage)
                    {
                        float offsetDelta = 0 - face.Descender * previousLineMaxScale + (face.Ascender + gap + m_lineSpacing + m_paragraphSpacing + m_lineSpacingDelta) * m_maxFontScale;
                        m_lineOffset += offsetDelta - lineOffsetDelta;
                        AdjustLineOffset(m_firstCharacterOfLine, m_characterCount, offsetDelta - lineOffsetDelta);
                    }
                    m_isNewPage = false;

                    // Calculate lineAscender & make sure if last character is superscript or subscript that we check that as well.
                    float lineAscender = m_fontAsset.fontInfo.Ascender * m_maxFontScale - m_lineOffset;
                    float lineAscender2 = m_fontAsset.fontInfo.Ascender * m_fontScale - m_lineOffset + m_baselineOffset;
                    lineAscender = lineAscender > lineAscender2 ? lineAscender : lineAscender2;

                    // Calculate lineDescender & make sure if last character is superscript or subscript that we check that as well.
                    float lineDescender = m_fontAsset.fontInfo.Descender * m_maxFontScale - m_lineOffset;
                    float lineDescender2 = m_fontAsset.fontInfo.Descender * m_fontScale - m_lineOffset + m_baselineOffset;
                    lineDescender = lineDescender < lineDescender2 ? lineDescender : lineDescender2;

                    // Update maxDescender and maxVisibleDescender
                    m_maxDescender = m_maxDescender < lineDescender ? m_maxDescender : lineDescender;
                    if (!isMaxVisibleDescenderSet)
                        maxVisibleDescender = m_maxDescender;

                    if (m_characterCount >= m_maxVisibleCharacters || m_lineNumber >= m_maxVisibleLines)
                        isMaxVisibleDescenderSet = true;

                    // Save Line Information
                    m_textInfo.lineInfo[m_lineNumber].firstCharacterIndex = m_firstCharacterOfLine;
                    m_textInfo.lineInfo[m_lineNumber].firstVisibleCharacterIndex = m_firstVisibleCharacterOfLine;
                    m_textInfo.lineInfo[m_lineNumber].lastCharacterIndex = m_characterCount;
                    m_textInfo.lineInfo[m_lineNumber].lastVisibleCharacterIndex = m_lastVisibleCharacterOfLine >= m_firstVisibleCharacterOfLine ? m_lastVisibleCharacterOfLine : m_firstVisibleCharacterOfLine;
                    m_textInfo.lineInfo[m_lineNumber].characterCount = m_textInfo.lineInfo[m_lineNumber].lastCharacterIndex - m_textInfo.lineInfo[m_lineNumber].firstCharacterIndex + 1;

                    m_textInfo.lineInfo[m_lineNumber].lineExtents.min = new Vector2(m_textInfo.characterInfo[m_firstVisibleCharacterOfLine].bottomLeft.x, lineDescender);
                    m_textInfo.lineInfo[m_lineNumber].lineExtents.max = new Vector2(m_textInfo.characterInfo[m_lastVisibleCharacterOfLine].topRight.x, lineAscender);
                    m_textInfo.lineInfo[m_lineNumber].lineLength = m_textInfo.lineInfo[m_lineNumber].lineExtents.max.x - (padding * m_maxFontScale);
                    m_textInfo.lineInfo[m_lineNumber].maxAdvance = m_textInfo.characterInfo[m_lastVisibleCharacterOfLine].xAdvance - m_characterSpacing * m_fontScale;
                    m_textInfo.lineInfo[m_lineNumber].maxScale = m_maxFontScale;

                    m_firstCharacterOfLine = m_characterCount + 1;

                    // Store PreferredWidth paying attention to linefeed and last character of text.
                    if (charCode == 10 && m_characterCount != totalCharacterCount - 1)
                    {
                        m_maxXAdvance = Mathf.Max(m_maxXAdvance, m_renderedWidth + m_xAdvance);
                        m_renderedWidth = 0;
                    }
                    else
                        m_renderedWidth = Mathf.Max(m_maxXAdvance, m_renderedWidth + m_xAdvance);
               
                    m_renderedHeight = m_maxAscender - m_maxDescender;

                    //Debug.Log("Line # " + m_lineNumber + "  Max Font Scale: " + m_maxFontScale + "  Next line Scale: " + m_fontScale);
                    //Debug.Log("LineInfo for line # " + (m_lineNumber) + " First character [" + m_textInfo.characterInfo[m_textInfo.lineInfo[m_lineNumber].firstCharacterIndex].character + "] at Index: " + m_textInfo.lineInfo[m_lineNumber].firstCharacterIndex +
                    //                                                    " First visible character [" + m_textInfo.characterInfo[m_textInfo.lineInfo[m_lineNumber].firstVisibleCharacterIndex].character + "] at Index: " + m_textInfo.lineInfo[m_lineNumber].firstVisibleCharacterIndex +
                    //                                                    " Last character [" + m_textInfo.characterInfo[m_textInfo.lineInfo[m_lineNumber].lastCharacterIndex].character + "] at index: " + m_textInfo.lineInfo[m_lineNumber].lastCharacterIndex +
                    //                                                    " Last Visible character [" + m_textInfo.characterInfo[m_textInfo.lineInfo[m_lineNumber].lastVisibleCharacterIndex].character + "] at index: " + m_textInfo.lineInfo[m_lineNumber].lastVisibleCharacterIndex +
                    //                                                    " Character Count of " + m_textInfo.lineInfo[m_lineNumber].characterCount /* + " Line Length of " + m_textInfo.lineInfo[m_lineNumber].lineLength +
                    //                                                    "  MinX: " + m_textInfo.lineInfo[m_lineNumber].lineExtents.min.x + "  MinY: " + m_textInfo.lineInfo[m_lineNumber].lineExtents.min.y +
                    //                                                    "  MaxX: " + m_textInfo.lineInfo[m_lineNumber].lineExtents.max.x + "  MaxY: " + m_textInfo.lineInfo[m_lineNumber].lineExtents.max.y +
                    //                                                    "  Line Ascender: " + lineAscender + "  Line Descender: " + lineDescender */ );


                    // Add new line if not last lines or character.
                    if (charCode == 10)
                    {
                        // Store the state of the line before starting on the new line.
                        SaveWordWrappingState(ref m_SavedLineState, i, m_characterCount);
                        // Store the state of the last Character before the new line.
                        SaveWordWrappingState(ref m_SavedWordWrapState, i, m_characterCount);

                        m_lineNumber += 1;
                        isStartOfNewLine = true;

                        // Check to make sure Array is large enough to hold a new line.
                        if (m_lineNumber >= m_textInfo.lineInfo.Length)
                            ResizeLineExtents(m_lineNumber);

                        // Apply Line Spacing
                        float scale = (m_style & FontStyles.Subscript) == FontStyles.Subscript || (m_style & FontStyles.Superscript) == FontStyles.Superscript ? m_maxFontScale : m_fontScale;
                        lineOffsetDelta = 0 - face.Descender * m_maxFontScale + (face.Ascender + gap + m_lineSpacing + m_paragraphSpacing + m_lineSpacingDelta) * scale;
                        m_lineOffset += lineOffsetDelta;


                        previousLineMaxScale = m_maxFontScale;
                        firstVisibleCharacterScale = scale;
                        m_maxFontScale = 0;
                        spriteScale = 1;
                        m_xAdvance = 0 + tag_LineIndent + tag_Indent;

                        ellipsisIndex = m_characterCount - 1;
                    }
                }
                #endregion Check for Linefeed or Last Character


                // Store Rectangle positions for each Character and Mesh Extents.
                #region Save CharacterInfo for the current character.
                m_textInfo.characterInfo[m_characterCount].topLine = m_textInfo.characterInfo[m_characterCount].baseLine + m_currentFontAsset.fontInfo.Ascender * m_fontScale; // Ascender
                m_textInfo.characterInfo[m_characterCount].bottomLine = m_textInfo.characterInfo[m_characterCount].baseLine + m_currentFontAsset.fontInfo.Descender * m_fontScale; // Descender
                m_textInfo.characterInfo[m_characterCount].padding = padding * m_fontScale;
                m_textInfo.characterInfo[m_characterCount].aspectRatio = m_cached_GlyphInfo.width / m_cached_GlyphInfo.height;
                //m_textInfo.characterInfo[m_characterCount].scale = m_fontScale;


                // Determine the bounds of the Mesh.
                if (m_textInfo.characterInfo[m_characterCount].isVisible)
                {
                    m_meshExtents.min = new Vector2(Mathf.Min(m_meshExtents.min.x, m_textInfo.characterInfo[m_characterCount].vertex_BL.position.x), Mathf.Min(m_meshExtents.min.y, m_textInfo.characterInfo[m_characterCount].vertex_BL.position.y));
                    m_meshExtents.max = new Vector2(Mathf.Max(m_meshExtents.max.x, m_textInfo.characterInfo[m_characterCount].vertex_TR.position.x), Mathf.Max(m_meshExtents.max.y, m_textInfo.characterInfo[m_characterCount].vertex_TL.position.y));
                }


                // Save pageInfo Data
                if (charCode != 13 && charCode != 10 && m_pageNumber < 16)
                {
                    m_textInfo.pageInfo[m_pageNumber].ascender = pageAscender;
                    m_textInfo.pageInfo[m_pageNumber].descender = descender < m_textInfo.pageInfo[m_pageNumber].descender ? descender : m_textInfo.pageInfo[m_pageNumber].descender;
                    //Debug.Log("Char [" + (char)charCode + "] with ASCII (" + charCode + ") on Page # " + m_pageNumber + " with Ascender: " + m_textInfo.pageInfo[m_pageNumber].ascender + ". Descender: " + m_textInfo.pageInfo[m_pageNumber].descender);

                    if (m_pageNumber == 0 && m_characterCount == 0)
                        m_textInfo.pageInfo[m_pageNumber].firstCharacterIndex = m_characterCount;
                    else if (m_characterCount > 0 && m_pageNumber != m_textInfo.characterInfo[m_characterCount - 1].pageNumber)
                    {
                        m_textInfo.pageInfo[m_pageNumber - 1].lastCharacterIndex = m_characterCount - 1;
                        m_textInfo.pageInfo[m_pageNumber].firstCharacterIndex = m_characterCount;
                    }
                    else if (m_characterCount == totalCharacterCount - 1)
                        m_textInfo.pageInfo[m_pageNumber].lastCharacterIndex = m_characterCount;
                }
                #endregion Saving CharacterInfo


                // Save State of Mesh Creation for handling of Word Wrapping
                #region Save Word Wrapping State
                if (m_enableWordWrapping || m_overflowMode == TextOverflowModes.Truncate || m_overflowMode == TextOverflowModes.Ellipsis)
                {
                    if ((charCode == 9 || charCode == 32) && !m_isNonBreakingSpace)
                    {
                        // We store the state of numerous variables for the most recent Space, LineFeed or Carriage Return to enable them to be restored 
                        // for Word Wrapping.
                        SaveWordWrappingState(ref m_SavedWordWrapState, i, m_characterCount);
                        m_isCharacterWrappingEnabled = false;
                        isFirstWord = false;
                    }
                    else if (charCode > 0x2e80 && charCode < 0x9fff || m_fontAsset.lineBreakingInfo.leadingCharacters.ContainsKey(charCode) || m_fontAsset.lineBreakingInfo.followingCharacters.ContainsKey(charCode))
                    {
                        if (m_characterCount < totalCharacterCount - 1
                                && m_fontAsset.lineBreakingInfo.leadingCharacters.ContainsKey(charCode) == false
                                && m_fontAsset.lineBreakingInfo.followingCharacters.ContainsKey(m_VisibleCharacters[m_characterCount + 1]) == false)
                        {
                            SaveWordWrappingState(ref m_SavedWordWrapState, i, m_characterCount);
                            m_isCharacterWrappingEnabled = false;
                            isFirstWord = false;
                        }
                    }
                    else if ((isFirstWord || m_isCharacterWrappingEnabled == true || isLastBreakingChar))
                        SaveWordWrappingState(ref m_SavedWordWrapState, i, m_characterCount);
                }
                #endregion Save Word Wrapping State

                m_characterCount += 1;
            }


            // Check Auto Sizing and increase font size to fill text container.
            #region Check Auto-Sizing (Upper Font Size Bounds)
            fontSizeDelta = m_maxFontSize - m_minFontSize;
            if (!m_isCharacterWrappingEnabled && m_enableAutoSizing && fontSizeDelta > 0.051f && m_fontSize < m_fontSizeMax)
            {
                m_minFontSize = m_fontSize;
                m_fontSize += Mathf.Max((m_maxFontSize - m_fontSize) / 2, 0.05f);
                m_fontSize = (int)(Mathf.Min(m_fontSize, m_fontSizeMax) * 20 + 0.5f) / 20f;

                if (loopCountA > 20) return; // Added to debug
                GenerateTextMesh();
                return;
            }
            #endregion End Auto-sizing Check


            m_isCharacterWrappingEnabled = false;

            // Adjust Preferred Height to account for Margins.
            m_renderedHeight += m_margin.y > 0 ? m_margin.y : 0;
            
            if (m_renderMode == TextRenderFlags.GetPreferredSizes)
                return;

            if (!IsRectTransformDriven) { m_preferredWidth = m_renderedWidth; m_preferredHeight = m_renderedHeight; }

            // DEBUG & PERFORMANCE CHECKS (0.006ms)
            //Debug.Log("Iteration Count: " + loopCountA + ". Final Point Size: " + m_fontSize); // + "  B: " + loopCountB + "  C: " + loopCountC + "  D: " + loopCountD);

            // If there are no visible characters... no need to continue
            if (m_visibleCharacterCount == 0 && m_visibleSpriteCount == 0)
            {
                m_uiRenderer.SetMesh(null);

                //Vector3[] vertices = m_textInfo.meshInfo.vertices;

                //if (vertices != null)
                //{
                //    Array.Clear(vertices, 0, vertices.Length);
                //    m_mesh.vertices = vertices;
                //}
                return;
            }


            int last_vert_index = m_visibleCharacterCount * 4;
            // Partial clear of the vertices array to mark unused vertices as degenerate.
            Array.Clear(m_textInfo.meshInfo.vertices, last_vert_index, m_textInfo.meshInfo.vertices.Length - last_vert_index);
            // Do we want to clear the sprite array?

            // Handle Text Alignment
            #region Text Alignment
            switch (m_textAlignment)
            {
                // Top Vertically
                case TextAlignmentOptions.Top:
                case TextAlignmentOptions.TopLeft:
                case TextAlignmentOptions.TopJustified:
                case TextAlignmentOptions.TopRight:
                    if (m_overflowMode != TextOverflowModes.Page)
                        m_anchorOffset = m_rectCorners[1] + new Vector3(0 + margins.x, 0 - m_maxAscender - margins.y, 0);
                    else
                        m_anchorOffset = m_rectCorners[1] + new Vector3(0 + margins.x, 0 - m_textInfo.pageInfo[pageToDisplay].ascender - margins.y, 0);
                    break;

                // Middle Vertically
                case TextAlignmentOptions.Left:
                case TextAlignmentOptions.Right:
                case TextAlignmentOptions.Center:
                case TextAlignmentOptions.Justified:
                    if (m_overflowMode != TextOverflowModes.Page)
                        m_anchorOffset = (m_rectCorners[0] + m_rectCorners[1]) / 2 + new Vector3(0 + margins.x, 0 - (m_maxAscender + margins.y + maxVisibleDescender - margins.w) / 2, 0);
                    else
                        m_anchorOffset = (m_rectCorners[0] + m_rectCorners[1]) / 2 + new Vector3(0 + margins.x, 0 - (m_textInfo.pageInfo[pageToDisplay].ascender + margins.y + m_textInfo.pageInfo[pageToDisplay].descender - margins.w) / 2, 0);
                    break;

                // Bottom Vertically
                case TextAlignmentOptions.Bottom:
                case TextAlignmentOptions.BottomLeft:
                case TextAlignmentOptions.BottomRight:
                case TextAlignmentOptions.BottomJustified:
                    if (m_overflowMode != TextOverflowModes.Page)
                        m_anchorOffset = m_rectCorners[0] + new Vector3(0 + margins.x, 0 - maxVisibleDescender + margins.w, 0);
                    else
                        m_anchorOffset = m_rectCorners[0] + new Vector3(0 + margins.x, 0 - m_textInfo.pageInfo[pageToDisplay].descender + margins.w, 0);
                    break;
                    
                // Baseline Vertically
                case TextAlignmentOptions.Baseline:
                case TextAlignmentOptions.BaselineLeft:
                case TextAlignmentOptions.BaselineRight:
                case TextAlignmentOptions.BaselineJustified:
                    m_anchorOffset = (m_rectCorners[0] + m_rectCorners[1]) / 2 + new Vector3(0 + margins.x, 0, 0);
                    break;

                // Midline Vertically 
                case TextAlignmentOptions.MidlineLeft:
                case TextAlignmentOptions.Midline:
                case TextAlignmentOptions.MidlineRight:
                case TextAlignmentOptions.MidlineJustified:
                    m_anchorOffset = (m_rectCorners[0] + m_rectCorners[1]) / 2 + new Vector3(0 + margins.x, 0 - (m_meshExtents.max.y + margins.y + m_meshExtents.min.y - margins.w) / 2, 0);
                    break;
            }
            #endregion Text Alignment


            // Initialization for Second Pass
            Vector3 justificationOffset = Vector3.zero;
            Vector3 offset = Vector3.zero;
            int vert_index_X4 = 0;
            int sprite_index_X4 = 0;
            //Array.Clear(m_meshAllocCount, 0, 17);

            int wordCount = 0;
            int lineCount = 0;
            int lastLine = 0;

            bool isStartOfWord = false;
            int wordFirstChar = 0;
            int wordLastChar = 0;

            // Second Pass : Line Justification, UV Mapping, Character & Line Visibility & more.
            #region Handle Line Justification & UV Mapping & Character Visibility & More
            
            // Variables used to handle Canvas Render Modes and SDF Scaling
            bool isCameraAssigned = m_canvas.worldCamera == null ? false : true;
            float lossyScale = m_rectTransform.lossyScale.z;
            RenderMode canvasRenderMode = m_canvas.renderMode;
            float canvasScaleFactor = m_canvas.scaleFactor;

            int underlineSegmentCount = 0;
            Color32 underlineColor = Color.white;
            Color32 strikethroughColor = Color.white;
            float underlineStartScale = 0;
            float underlineEndScale = 0;
            float underlineMaxScale = 0;
            float underlineBaseLine = Mathf.Infinity;
            int lastPage = 0;

            float strikethroughPointSize = 0;
            float strikethroughScale = 0;
            float strikethroughBaseline = 0;

            TMP_CharacterInfo[] characterInfos = m_textInfo.characterInfo;
            for (int i = 0; i < m_characterCount; i++)
            {
                int currentLine = characterInfos[i].lineNumber;
                char currentCharacter = characterInfos[i].character;
                TMP_LineInfo lineInfo = m_textInfo.lineInfo[currentLine];
                
                TextAlignmentOptions lineAlignment = lineInfo.alignment;
                lineCount = currentLine + 1;

                // Process Line Justification
                #region Handle Line Justification
                //if (!characterInfos[i].isIgnoringAlignment)
                //{
                switch (lineAlignment)
                {
                    case TextAlignmentOptions.TopLeft:
                    case TextAlignmentOptions.Left:
                    case TextAlignmentOptions.BottomLeft:
                    case TextAlignmentOptions.BaselineLeft:
                    case TextAlignmentOptions.MidlineLeft:
                        justificationOffset = new Vector3 (0 + lineInfo.marginLeft, 0, 0);
                        break;

                    case TextAlignmentOptions.Top:
                    case TextAlignmentOptions.Center:
                    case TextAlignmentOptions.Bottom:
                    case TextAlignmentOptions.Baseline:
                    case TextAlignmentOptions.Midline:
                        justificationOffset = new Vector3(lineInfo.marginLeft + lineInfo.width / 2 - lineInfo.maxAdvance / 2, 0, 0);
                        break;

                    case TextAlignmentOptions.TopRight:
                    case TextAlignmentOptions.Right:
                    case TextAlignmentOptions.BottomRight:
                    case TextAlignmentOptions.BaselineRight:
                    case TextAlignmentOptions.MidlineRight:
                        justificationOffset = new Vector3(lineInfo.marginLeft + lineInfo.width - lineInfo.maxAdvance, 0, 0);
                        break;

                    case TextAlignmentOptions.TopJustified:
                    case TextAlignmentOptions.Justified:
                    case TextAlignmentOptions.BottomJustified:
                    case TextAlignmentOptions.BaselineJustified:
                    case TextAlignmentOptions.MidlineJustified:
                        charCode = m_textInfo.characterInfo[i].character;
                        char lastCharOfCurrentLine = m_textInfo.characterInfo[lineInfo.lastCharacterIndex].character;

                        if (/*char.IsWhiteSpace(lastCharOfCurrentLine) &&*/ !char.IsControl(lastCharOfCurrentLine) && currentLine < m_lineNumber)
                        {
                            // All lines are justified accept the last one.
                            float gap = lineInfo.width - lineInfo.maxAdvance;

                            if (currentLine != lastLine || i == 0)
                                justificationOffset = new Vector3(lineInfo.marginLeft, 0, 0);
                            else
                            {
                                if (charCode == 9 || charCode == 32 || charCode == 160)
                                {
                                    int spaces = lineInfo.spaceCount - 1 > 0 ? lineInfo.spaceCount - 1 : 1;
                                    justificationOffset += new Vector3(gap * (1 - m_wordWrappingRatios) / (spaces), 0, 0);
                                }
                                else
                                {
                                    justificationOffset += new Vector3(gap * m_wordWrappingRatios / (lineInfo.characterCount - lineInfo.spaceCount - 1), 0, 0);
                                }
                            }
                        }
                        else
                            justificationOffset = new Vector3(lineInfo.marginLeft, 0, 0); // Keep last line left justified.

                        //Debug.Log("Char [" + (char)charCode + "] Code:" + charCode + "  Line # " + currentLine + "  Offset:" + justificationOffset + "  # Spaces:" + lineInfo.spaceCount + "  # Characters:" + lineInfo.characterCount);
                        break;
                }
                //}
                #endregion End Text Justification

                offset = m_anchorOffset + justificationOffset;

                // Handle Visible Characters
                #region Handle Visible Characters
                if (characterInfos[i].isVisible)
                {
                    TMP_CharacterType type = characterInfos[i].type;
                    switch (type)
                    {
                        // CHARACTERS
                        case TMP_CharacterType.Character:

                            Extents lineExtents = lineInfo.lineExtents;
                            float uvOffset = (m_uvLineOffset * currentLine) % 1 + m_uvOffset.x;

                            // Setup UV2 based on Character Mapping Options Selected
                            #region Handle UV Mapping Options
                            switch (m_horizontalMapping)
                            {
                                case TextureMappingOptions.Character:
                                    characterInfos[i].vertex_BL.uv2.x = 0 + m_uvOffset.x;
                                    characterInfos[i].vertex_TL.uv2.x = 0 + m_uvOffset.x;
                                    characterInfos[i].vertex_TR.uv2.x = 1 + m_uvOffset.x;
                                    characterInfos[i].vertex_BR.uv2.x = 1 + m_uvOffset.x;
                                    break;

                                case TextureMappingOptions.Line:
                                    if (m_textAlignment != TextAlignmentOptions.Justified)
                                    {
                                        characterInfos[i].vertex_BL.uv2.x = (characterInfos[i].vertex_BL.position.x - lineExtents.min.x) / (lineExtents.max.x - lineExtents.min.x) + uvOffset;
                                        characterInfos[i].vertex_TL.uv2.x = (characterInfos[i].vertex_TL.position.x - lineExtents.min.x) / (lineExtents.max.x - lineExtents.min.x) + uvOffset;
                                        characterInfos[i].vertex_TR.uv2.x = (characterInfos[i].vertex_TR.position.x - lineExtents.min.x) / (lineExtents.max.x - lineExtents.min.x) + uvOffset;
                                        characterInfos[i].vertex_BR.uv2.x = (characterInfos[i].vertex_BR.position.x - lineExtents.min.x) / (lineExtents.max.x - lineExtents.min.x) + uvOffset;
                                        break;
                                    }
                                    else // Special Case if Justified is used in Line Mode.
                                    {
                                        characterInfos[i].vertex_BL.uv2.x = (characterInfos[i].vertex_BL.position.x + justificationOffset.x - m_meshExtents.min.x) / (m_meshExtents.max.x - m_meshExtents.min.x) + uvOffset;
                                        characterInfos[i].vertex_TL.uv2.x = (characterInfos[i].vertex_TL.position.x + justificationOffset.x - m_meshExtents.min.x) / (m_meshExtents.max.x - m_meshExtents.min.x) + uvOffset;
                                        characterInfos[i].vertex_TR.uv2.x = (characterInfos[i].vertex_TR.position.x + justificationOffset.x - m_meshExtents.min.x) / (m_meshExtents.max.x - m_meshExtents.min.x) + uvOffset;
                                        characterInfos[i].vertex_BR.uv2.x = (characterInfos[i].vertex_BR.position.x + justificationOffset.x - m_meshExtents.min.x) / (m_meshExtents.max.x - m_meshExtents.min.x) + uvOffset;
                                        break;
                                    }

                                case TextureMappingOptions.Paragraph:
                                    characterInfos[i].vertex_BL.uv2.x = (characterInfos[i].vertex_BL.position.x + justificationOffset.x - m_meshExtents.min.x) / (m_meshExtents.max.x - m_meshExtents.min.x) + uvOffset;
                                    characterInfos[i].vertex_TL.uv2.x = (characterInfos[i].vertex_TL.position.x + justificationOffset.x - m_meshExtents.min.x) / (m_meshExtents.max.x - m_meshExtents.min.x) + uvOffset;
                                    characterInfos[i].vertex_TR.uv2.x = (characterInfos[i].vertex_TR.position.x + justificationOffset.x - m_meshExtents.min.x) / (m_meshExtents.max.x - m_meshExtents.min.x) + uvOffset;
                                    characterInfos[i].vertex_BR.uv2.x = (characterInfos[i].vertex_BR.position.x + justificationOffset.x - m_meshExtents.min.x) / (m_meshExtents.max.x - m_meshExtents.min.x) + uvOffset;
                                    break;

                                case TextureMappingOptions.MatchAspect:

                                    switch (m_verticalMapping)
                                    {
                                        case TextureMappingOptions.Character:
                                            characterInfos[i].vertex_BL.uv2.y = 0 + m_uvOffset.y;
                                            characterInfos[i].vertex_TL.uv2.y = 1 + m_uvOffset.y;
                                            characterInfos[i].vertex_TR.uv2.y = 0 + m_uvOffset.y;
                                            characterInfos[i].vertex_BR.uv2.y = 1 + m_uvOffset.y;
                                            break;

                                        case TextureMappingOptions.Line:
                                            characterInfos[i].vertex_BL.uv2.y = (characterInfos[i].vertex_BL.position.y - lineExtents.min.y) / (lineExtents.max.y - lineExtents.min.y) + uvOffset;
                                            characterInfos[i].vertex_TL.uv2.y = (characterInfos[i].vertex_TL.position.y - lineExtents.min.y) / (lineExtents.max.y - lineExtents.min.y) + uvOffset;
                                            characterInfos[i].vertex_TR.uv2.y = characterInfos[i].vertex_BL.uv2.y;
                                            characterInfos[i].vertex_BR.uv2.y = characterInfos[i].vertex_TL.uv2.y;
                                            break;

                                        case TextureMappingOptions.Paragraph:
                                            characterInfos[i].vertex_BL.uv2.y = (characterInfos[i].vertex_BL.position.y - m_meshExtents.min.y) / (m_meshExtents.max.y - m_meshExtents.min.y) + uvOffset;
                                            characterInfos[i].vertex_TL.uv2.y = (characterInfos[i].vertex_TL.position.y - m_meshExtents.min.y) / (m_meshExtents.max.y - m_meshExtents.min.y) + uvOffset;
                                            characterInfos[i].vertex_TR.uv2.y = characterInfos[i].vertex_BL.uv2.y;
                                            characterInfos[i].vertex_BR.uv2.y = characterInfos[i].vertex_TL.uv2.y;
                                            break;

                                        case TextureMappingOptions.MatchAspect:
                                            Debug.Log("ERROR: Cannot Match both Vertical & Horizontal.");
                                            break;
                                    }

                                    //float xDelta = 1 - (_uv2s[vert_index + 0].y * textMeshCharacterInfo[i].AspectRatio); // Left aligned
                                    float xDelta = (1 - ((characterInfos[i].vertex_BL.uv2.y +  characterInfos[i].vertex_TL.uv2.y) * characterInfos[i].aspectRatio)) / 2; // Center of Rectangle

                                    characterInfos[i].vertex_BL.uv2.x = (characterInfos[i].vertex_BL.uv2.y * characterInfos[i].aspectRatio) + xDelta + uvOffset;
                                    characterInfos[i].vertex_TL.uv2.x = characterInfos[i].vertex_BL.uv2.x;
                                    characterInfos[i].vertex_TR.uv2.x = (characterInfos[i].vertex_TL.uv2.y * characterInfos[i].aspectRatio) + xDelta + uvOffset;
                                    characterInfos[i].vertex_BR.uv2.x = characterInfos[i].vertex_TR.uv2.x;
                                    break;
                            }

                            switch (m_verticalMapping)
                            {
                                case TextureMappingOptions.Character:
                                    characterInfos[i].vertex_BL.uv2.y = 0 + m_uvOffset.y;
                                    characterInfos[i].vertex_TL.uv2.y = 1 + m_uvOffset.y;
                                    characterInfos[i].vertex_TR.uv2.y = 1 + m_uvOffset.y;
                                    characterInfos[i].vertex_BR.uv2.y = 0 + m_uvOffset.y;
                                    break;

                                case TextureMappingOptions.Line:
                                    characterInfos[i].vertex_BL.uv2.y = (characterInfos[i].vertex_BL.position.y - lineExtents.min.y) / (lineExtents.max.y - lineExtents.min.y) + m_uvOffset.y;
                                    characterInfos[i].vertex_TL.uv2.y = (characterInfos[i].vertex_TL.position.y - lineExtents.min.y) / (lineExtents.max.y - lineExtents.min.y) + m_uvOffset.y;
                                    characterInfos[i].vertex_BR.uv2.y = characterInfos[i].vertex_BL.uv2.y;
                                    characterInfos[i].vertex_TR.uv2.y = characterInfos[i].vertex_TL.uv2.y;
                                    break;

                                case TextureMappingOptions.Paragraph:
                                    characterInfos[i].vertex_BL.uv2.y = (characterInfos[i].vertex_BL.position.y - m_meshExtents.min.y) / (m_meshExtents.max.y - m_meshExtents.min.y) + m_uvOffset.y;
                                    characterInfos[i].vertex_TL.uv2.y = (characterInfos[i].vertex_TL.position.y - m_meshExtents.min.y) / (m_meshExtents.max.y - m_meshExtents.min.y) + m_uvOffset.y;
                                    characterInfos[i].vertex_BR.uv2.y = characterInfos[i].vertex_BL.uv2.y;
                                    characterInfos[i].vertex_TR.uv2.y = characterInfos[i].vertex_TL.uv2.y;
                                    break;

                                case TextureMappingOptions.MatchAspect:
                                    //float yDelta = 1 - (_uv2s[vert_index + 2].x / textMeshCharacterInfo[i].AspectRatio); // Top Corner
                                    float yDelta = (1 - ((characterInfos[i].vertex_BL.uv2.x + characterInfos[i].vertex_TR.uv2.x) / characterInfos[i].aspectRatio)) / 2; // Center of Rectangle
                                    //float yDelta = 0;

                                    characterInfos[i].vertex_BL.uv2.y = yDelta + (characterInfos[i].vertex_BL.uv2.x / characterInfos[i].aspectRatio) + m_uvOffset.y;
                                    characterInfos[i].vertex_TL.uv2.y = yDelta + (characterInfos[i].vertex_TR.uv2.x / characterInfos[i].aspectRatio) + m_uvOffset.y;
                                    characterInfos[i].vertex_BR.uv2.y = characterInfos[i].vertex_BL.uv2.y;
                                    characterInfos[i].vertex_TR.uv2.y = characterInfos[i].vertex_TL.uv2.y;
                                    break;
                            }
                            #endregion End UV Mapping Options


                            // Pack UV's so that we can pass Xscale needed for Shader to maintain 1:1 ratio.
                            #region Pack Scale into UV2
                            float xScale = characterInfos[i].scale * (1 - m_charWidthAdjDelta);
                            if ((characterInfos[i].style & FontStyles.Bold) == FontStyles.Bold) xScale *= -1;
                        
                            switch (canvasRenderMode)
                            {
                                case RenderMode.ScreenSpaceOverlay:
                                    xScale *= lossyScale / canvasScaleFactor;
                                    break;
                                case RenderMode.ScreenSpaceCamera:
                                    xScale *= isCameraAssigned ? lossyScale : 1;
                                    break;
                                case RenderMode.WorldSpace:
                                    xScale *= lossyScale;
                                    break;
                            }

                            float x0 = characterInfos[i].vertex_BL.uv2.x;
                            float y0 = characterInfos[i].vertex_BL.uv2.y;
                            float x1 = characterInfos[i].vertex_TR.uv2.x;
                            float y1 = characterInfos[i].vertex_TR.uv2.y; 

                            float dx = Mathf.Floor(x0);
                            float dy = Mathf.Floor(y0);

                            x0 = x0 - dx;
                            x1 = x1 - dx;
                            y0 = y0 - dy;
                            y1 = y1 - dy;

                            characterInfos[i].vertex_BL.uv2 = PackUV(x0, y0, xScale);
                            characterInfos[i].vertex_TL.uv2 = PackUV(x0, y1, xScale);
                            characterInfos[i].vertex_TR.uv2 = PackUV(x1, y1, xScale);
                            characterInfos[i].vertex_BR.uv2 = PackUV(x1, y0, xScale);
                            #endregion
                            
                            break;
                        
                        // SPRITES
                        case TMP_CharacterType.Sprite:
                            // Nothing right now
                            break;
                    }


                    // Handle maxVisibleCharacters, maxVisibleLines and Overflow Page Mode.
                    #region Handle maxVisibleCharacters / maxVisibleLines / Page Mode
                    if (i < m_maxVisibleCharacters && currentLine < m_maxVisibleLines && m_overflowMode != TextOverflowModes.Page)
                    {
                        characterInfos[i].vertex_BL.position += offset;
                        characterInfos[i].vertex_TL.position += offset;
                        characterInfos[i].vertex_TR.position += offset;
                        characterInfos[i].vertex_BR.position += offset;
                    }
                    else if (i < m_maxVisibleCharacters && currentLine < m_maxVisibleLines && m_overflowMode == TextOverflowModes.Page && characterInfos[i].pageNumber == pageToDisplay)
                    {
                        characterInfos[i].vertex_BL.position += offset;
                        characterInfos[i].vertex_TL.position += offset;
                        characterInfos[i].vertex_TR.position += offset;
                        characterInfos[i].vertex_BR.position += offset;
                    }
                    else
                    {
                        characterInfos[i].vertex_BL.position *= 0;
                        characterInfos[i].vertex_TL.position *= 0;
                        characterInfos[i].vertex_TR.position *= 0;
                        characterInfos[i].vertex_BR.position *= 0;
                    }
                    #endregion


                    // Fill Vertex Buffers for the various types of element
                    if (type == TMP_CharacterType.Character)
                    {
                        FillCharacterVertexBuffers(i, vert_index_X4);
                        vert_index_X4 += 4;
                    }
                    else if (type == TMP_CharacterType.Sprite)
                    {
                        FillSpriteVertexBuffers(i, sprite_index_X4);
                        sprite_index_X4 += 4;
                    }

                }
                #endregion


                // Apply Alignment and Justification Offset
                m_textInfo.characterInfo[i].bottomLeft += offset;
                m_textInfo.characterInfo[i].topLeft += offset;
                m_textInfo.characterInfo[i].topRight += offset;
                m_textInfo.characterInfo[i].bottomRight += offset;

                // Need to add top left and bottom right.
                m_textInfo.characterInfo[i].topLine += offset.y;
                m_textInfo.characterInfo[i].bottomLine += offset.y;
                m_textInfo.characterInfo[i].baseLine += offset.y;


                // Store Max Ascender & Descender
                if (currentCharacter != 10 && currentCharacter != 13)
                {
                    m_textInfo.lineInfo[currentLine].ascender = m_textInfo.characterInfo[i].topLine > m_textInfo.lineInfo[currentLine].ascender ? m_textInfo.characterInfo[i].topLine : m_textInfo.lineInfo[currentLine].ascender;
                    m_textInfo.lineInfo[currentLine].descender = m_textInfo.characterInfo[i].bottomLine < m_textInfo.lineInfo[currentLine].descender ? m_textInfo.characterInfo[i].bottomLine : m_textInfo.lineInfo[currentLine].descender;
                }


                // Need to recompute lineExtent to account for the offset from justification.
                #region Adjust lineExtents resulting from alignment offset
                if (currentLine != lastLine || i == m_characterCount - 1)
                {
                    // Update the previous line's extents
                    if (currentLine != lastLine)
                    {
                        m_textInfo.lineInfo[lastLine].lineExtents.min = new Vector2(m_textInfo.characterInfo[m_textInfo.lineInfo[lastLine].firstCharacterIndex].bottomLeft.x, m_textInfo.lineInfo[lastLine].descender);
                        m_textInfo.lineInfo[lastLine].lineExtents.max = new Vector2(m_textInfo.characterInfo[m_textInfo.lineInfo[lastLine].lastVisibleCharacterIndex].topRight.x, m_textInfo.lineInfo[lastLine].ascender);
                    }

                    // Update the current line's extents
                    if (i == m_characterCount - 1)
                    {
                        m_textInfo.lineInfo[currentLine].lineExtents.min = new Vector2(m_textInfo.characterInfo[m_textInfo.lineInfo[currentLine].firstCharacterIndex].bottomLeft.x, m_textInfo.lineInfo[currentLine].descender);
                        m_textInfo.lineInfo[currentLine].lineExtents.max = new Vector2(m_textInfo.characterInfo[m_textInfo.lineInfo[currentLine].lastVisibleCharacterIndex].topRight.x, m_textInfo.lineInfo[currentLine].ascender);
                    }
                }
                #endregion


                // Track Word Count per line and for the object
                #region Track Word Count
                if (char.IsLetterOrDigit(currentCharacter) || currentCharacter == 39 || currentCharacter == 8217)
                {
                    if (isStartOfWord == false)
                    {
                        isStartOfWord = true;
                        wordFirstChar = i;
                    }

                    // If last character is a word
                    if (isStartOfWord && i == m_characterCount - 1)
                    {
                        wordLastChar = i;
                        wordCount += 1;
                        m_textInfo.lineInfo[currentLine].wordCount += 1;

                        TMP_WordInfo wordInfo = new TMP_WordInfo();
                        wordInfo.firstCharacterIndex = wordFirstChar;
                        wordInfo.lastCharacterIndex = wordLastChar;
                        wordInfo.characterCount = wordLastChar - wordFirstChar + 1;
                        m_textInfo.wordInfo.Add(wordInfo);
                    }
                }
                else if (isStartOfWord || i == 0 && (char.IsPunctuation(currentCharacter) || char.IsWhiteSpace(currentCharacter) || i == m_characterCount - 1))
                {
                    wordLastChar = i == m_characterCount - 1 && char.IsLetterOrDigit(currentCharacter) ? i : i - 1;
                    isStartOfWord = false;

                    wordCount += 1;
                    m_textInfo.lineInfo[currentLine].wordCount += 1;

                    TMP_WordInfo wordInfo = new TMP_WordInfo();
                    wordInfo.firstCharacterIndex = wordFirstChar;
                    wordInfo.lastCharacterIndex = wordLastChar;
                    wordInfo.characterCount = wordLastChar - wordFirstChar + 1;
                    m_textInfo.wordInfo.Add(wordInfo);
                }
                #endregion


                // Setup & Handle Underline
                #region Underline
                // NOTE: Need to figure out how underline will be handled with multiple fonts and which font will be used for the underline.
                bool isUnderline = (m_textInfo.characterInfo[i].style & FontStyles.Underline) == FontStyles.Underline;
                if (isUnderline)
                {
                    bool isUnderlineVisible = true;
                    int currentPage = m_textInfo.characterInfo[i].pageNumber;

                    if (i > m_maxVisibleCharacters || currentLine > m_maxVisibleLines || (m_overflowMode == TextOverflowModes.Page && currentPage + 1 != m_pageToDisplay))
                        isUnderlineVisible = false;

                    // We only use the scale of visible characters.
                    if (currentCharacter != 10 && currentCharacter != 13 && currentCharacter != 32 && currentCharacter != 160)
                    {
                        underlineMaxScale = Mathf.Max(underlineMaxScale, m_textInfo.characterInfo[i].scale);
                        underlineBaseLine = Mathf.Min(currentPage == lastPage ? underlineBaseLine : Mathf.Infinity, m_textInfo.characterInfo[i].baseLine + font.fontInfo.Underline * underlineMaxScale);
                        lastPage = currentPage; // Need to track pages to ensure we reset baseline for the new pages.
                    }

                    if (beginUnderline == false && isUnderlineVisible == true && i <= lineInfo.lastVisibleCharacterIndex && currentCharacter != 10 && currentCharacter != 13)
                    {
                        if (i == lineInfo.lastVisibleCharacterIndex && (currentCharacter == 32 || currentCharacter == 160))
                        { }
                        else
                        {
                            beginUnderline = true;
                            underlineStartScale = m_textInfo.characterInfo[i].scale;
                            if (underlineMaxScale == 0) underlineMaxScale = underlineStartScale;
                            underline_start = new Vector3(m_textInfo.characterInfo[i].bottomLeft.x, underlineBaseLine, 0);
                            underlineColor = m_textInfo.characterInfo[i].color;
                        }
                    }

                    // End Underline if text only contains one character.
                    if (beginUnderline && m_characterCount == 1)
                    {
                        beginUnderline = false;
                        underline_end = new Vector3(m_textInfo.characterInfo[i].topRight.x, underlineBaseLine, 0);
                        underlineEndScale = m_textInfo.characterInfo[i].scale;

                        DrawUnderlineMesh(underline_start, underline_end, ref last_vert_index, underlineStartScale, underlineEndScale, underlineMaxScale, underlineColor);
                        underlineSegmentCount += 1;
                        underlineMaxScale = 0;
                        underlineBaseLine = Mathf.Infinity;
                    }
                    else if (beginUnderline && (i == lineInfo.lastCharacterIndex || i >= lineInfo.lastVisibleCharacterIndex))
                    {
                        // Terminate underline at previous visible character if space or carriage return.
                        if (currentCharacter == 10 || currentCharacter == 13 || currentCharacter == 32 || currentCharacter == 160)
                        {
                            int lastVisibleCharacterIndex = lineInfo.lastVisibleCharacterIndex;
                            underline_end = new Vector3(m_textInfo.characterInfo[lastVisibleCharacterIndex].topRight.x, underlineBaseLine, 0);
                            underlineEndScale = m_textInfo.characterInfo[lastVisibleCharacterIndex].scale;
                        }
                        else
                        {   // End underline if last character of the line.
                            underline_end = new Vector3(m_textInfo.characterInfo[i].topRight.x, underlineBaseLine, 0);
                            underlineEndScale = m_textInfo.characterInfo[i].scale;
                        }

                        beginUnderline = false;
                        DrawUnderlineMesh(underline_start, underline_end, ref last_vert_index, underlineStartScale, underlineEndScale, underlineMaxScale, underlineColor);
                        underlineSegmentCount += 1;
                        underlineMaxScale = 0;
                        underlineBaseLine = Mathf.Infinity;
                    }
                    else if (beginUnderline && !isUnderlineVisible)
                    {
                        beginUnderline = false;
                        underline_end = new Vector3(m_textInfo.characterInfo[i - 1].topRight.x, underlineBaseLine, 0);
                        underlineEndScale = m_textInfo.characterInfo[i - 1].scale;

                        DrawUnderlineMesh(underline_start, underline_end, ref last_vert_index, underlineStartScale, underlineEndScale, underlineMaxScale, underlineColor);
                        underlineSegmentCount += 1;
                        underlineMaxScale = 0;
                        underlineBaseLine = Mathf.Infinity;
                    }
                }
                else
                {
                    // End Underline
                    if (beginUnderline == true)
                    {
                        beginUnderline = false;
                        underline_end = new Vector3(m_textInfo.characterInfo[i - 1].topRight.x, underlineBaseLine, 0);
                        underlineEndScale = m_textInfo.characterInfo[i - 1].scale;

                        DrawUnderlineMesh(underline_start, underline_end, ref last_vert_index, underlineStartScale, underlineEndScale, underlineMaxScale, underlineColor);
                        underlineSegmentCount += 1;
                        underlineMaxScale = 0;
                        underlineBaseLine = Mathf.Infinity;
                    }
                }
                #endregion


                // Setup & Handle Strikethrough
                #region Strikethrough
                // NOTE: Need to figure out how underline will be handled with multiple fonts and which font will be used for the underline.
                bool isStrikethrough = (m_textInfo.characterInfo[i].style & FontStyles.Strikethrough) == FontStyles.Strikethrough;
                if (isStrikethrough)
                {
                    bool isStrikeThroughVisible = true;

                    if (i > m_maxVisibleCharacters || currentLine > m_maxVisibleLines || (m_overflowMode == TextOverflowModes.Page && m_textInfo.characterInfo[i].pageNumber + 1 != m_pageToDisplay))
                        isStrikeThroughVisible = false;

                    if (beginStrikethrough == false && isStrikeThroughVisible && i <= lineInfo.lastVisibleCharacterIndex && currentCharacter != 10 && currentCharacter != 13)
                    {
                        if (i == lineInfo.lastVisibleCharacterIndex && (currentCharacter == 32 || currentCharacter == 160))
                        { }
                        else
                        {
                            beginStrikethrough = true;
                            strikethroughPointSize = m_textInfo.characterInfo[i].pointSize;
                            strikethroughScale = m_textInfo.characterInfo[i].scale;
                            strikethrough_start = new Vector3(m_textInfo.characterInfo[i].bottomLeft.x, m_textInfo.characterInfo[i].baseLine + (font.fontInfo.Ascender + font.fontInfo.Descender) / 2.75f * strikethroughScale, 0);
                            strikethroughColor = m_textInfo.characterInfo[i].color;
                            strikethroughBaseline = m_textInfo.characterInfo[i].baseLine;
                            //Debug.Log("Char [" + currentCharacter + "] Start Strikethrough POS: " + strikethrough_start);
                        }
                    }

                    // End Strikethrough if text only contains one character.
                    if (beginStrikethrough && m_characterCount == 1)
                    {
                        beginStrikethrough = false;
                        strikethrough_end = new Vector3(m_textInfo.characterInfo[i].topRight.x, m_textInfo.characterInfo[i].baseLine + (font.fontInfo.Ascender + font.fontInfo.Descender) / 2 * strikethroughScale, 0);

                        DrawUnderlineMesh(strikethrough_start, strikethrough_end, ref last_vert_index, strikethroughScale, strikethroughScale, strikethroughScale, strikethroughColor);
                        underlineSegmentCount += 1;
                    }
                    else if (beginStrikethrough && i == lineInfo.lastCharacterIndex)
                    {
                        // Terminate Strikethrough at previous visible character if space or carriage return.
                        if (currentCharacter == 10 || currentCharacter == 13 || currentCharacter == 32 || currentCharacter == 160)
                        {
                            int lastVisibleCharacterIndex = lineInfo.lastVisibleCharacterIndex;
                            strikethrough_end = new Vector3(m_textInfo.characterInfo[lastVisibleCharacterIndex].topRight.x, m_textInfo.characterInfo[lastVisibleCharacterIndex].baseLine + (font.fontInfo.Ascender + font.fontInfo.Descender) / 2 * strikethroughScale, 0);
                        }
                        else
                        {
                            // Terminate Strikethrough at last character of line.
                            strikethrough_end = new Vector3(m_textInfo.characterInfo[i].topRight.x, m_textInfo.characterInfo[i].baseLine + (font.fontInfo.Ascender + font.fontInfo.Descender) / 2 * strikethroughScale, 0);
                        }

                        beginStrikethrough = false;
                        DrawUnderlineMesh(strikethrough_start, strikethrough_end, ref last_vert_index, strikethroughScale, strikethroughScale, strikethroughScale, strikethroughColor);
                        underlineSegmentCount += 1;
                    }
                    else if (beginStrikethrough && i < m_characterCount && (m_textInfo.characterInfo[i + 1].pointSize != strikethroughPointSize || !TMP_Math.Equals(m_textInfo.characterInfo[i + 1].baseLine + offset.y, strikethroughBaseline)))
                    {
                        // Terminate Strikethrough if scale changes.
                        beginStrikethrough = false;

                        int lastVisibleCharacterIndex = lineInfo.lastVisibleCharacterIndex;
                        if (i > lastVisibleCharacterIndex)
                            strikethrough_end = new Vector3(m_textInfo.characterInfo[lastVisibleCharacterIndex].topRight.x, m_textInfo.characterInfo[lastVisibleCharacterIndex].baseLine + (font.fontInfo.Ascender + font.fontInfo.Descender) / 2 * strikethroughScale, 0);
                        else
                            strikethrough_end = new Vector3(m_textInfo.characterInfo[i].topRight.x, m_textInfo.characterInfo[i].baseLine + (font.fontInfo.Ascender + font.fontInfo.Descender) / 2 * strikethroughScale, 0);

                        DrawUnderlineMesh(strikethrough_start, strikethrough_end, ref last_vert_index, strikethroughScale, strikethroughScale, strikethroughScale, strikethroughColor);
                        underlineSegmentCount += 1;
                        //Debug.Log("Char [" + currentCharacter + "] at Index: " + i + "  End Strikethrough POS: " + strikethrough_end + "  Baseline: " + m_textInfo.characterInfo[i].baseLine.ToString("f3"));
                    }
                    else if (beginStrikethrough && !isStrikeThroughVisible)
                    {
                        // Terminate Strikethrough if character is not visible.
                        beginStrikethrough = false;
                        strikethrough_end = new Vector3(m_textInfo.characterInfo[i - 1].topRight.x, m_textInfo.characterInfo[i - 1].baseLine + (font.fontInfo.Ascender + font.fontInfo.Descender) / 2 * strikethroughScale, 0);

                        DrawUnderlineMesh(strikethrough_start, strikethrough_end, ref last_vert_index, strikethroughScale, strikethroughScale, strikethroughScale, strikethroughColor);
                        underlineSegmentCount += 1;
                    }
                }
                else
                {
                    // End Underline
                    if (beginStrikethrough == true)
                    {
                        beginStrikethrough = false;
                        strikethrough_end = new Vector3(m_textInfo.characterInfo[i - 1].topRight.x, m_textInfo.characterInfo[i - 1].baseLine + (font.fontInfo.Ascender + font.fontInfo.Descender) / 2 * m_fontScale, 0);

                        DrawUnderlineMesh(strikethrough_start, strikethrough_end, ref last_vert_index, strikethroughScale, strikethroughScale, strikethroughScale, strikethroughColor);
                        underlineSegmentCount += 1;
                    }
                }
                #endregion


                lastLine = currentLine;
            }
            #endregion


            // METRICS ABOUT THE TEXT OBJECT
            m_textInfo.characterCount = (short)m_characterCount;
            m_textInfo.spriteCount = m_spriteCount;
            m_textInfo.lineCount = (short)lineCount;
            m_textInfo.wordCount = wordCount != 0 && m_characterCount > 0 ? (short)wordCount : (short)1;
            m_textInfo.pageCount = m_pageNumber + 1;


            // If Advanced Layout Component is present, don't upload the mesh.
            if (m_renderMode == TextRenderFlags.Render) // m_isAdvanceLayoutComponentPresent == false || m_advancedLayoutComponent.isEnabled == false)
            {
                //Debug.Log("Uploading Mesh normally.");

                // Upload Mesh Data
                m_mesh.vertices = m_textInfo.meshInfo.vertices;
                m_mesh.uv = m_textInfo.meshInfo.uvs0;
                m_mesh.uv2 = m_textInfo.meshInfo.uvs2;
                m_mesh.colors32 = m_textInfo.meshInfo.colors32;

                m_mesh.RecalculateBounds(); // Replace by manual bound calculation to improve performance.

                m_uiRenderer.SetMesh(m_mesh);


                if (m_inlineGraphics != null)
                    m_inlineGraphics.DrawSprite(m_inlineGraphics.uiVertex, m_visibleSpriteCount);

            }

            // Compute Bounds for the mesh. Manual computation is more efficient then using Mesh.recalcualteBounds.
            m_bounds = new Bounds(new Vector3((m_meshExtents.max.x + m_meshExtents.min.x) / 2, (m_meshExtents.max.y + m_meshExtents.min.y) / 2, 0) + offset, new Vector3(m_meshExtents.max.x - m_meshExtents.min.x, m_meshExtents.max.y - m_meshExtents.min.y, 0));

            // Has Text Container's Width or Height been specified by the user?
            /*
            if (m_rectTransform.sizeDelta.x == 0 || m_rectTransform.sizeDelta.y == 0)
            {
                //Debug.Log("Auto-fitting Text. Default Width:" + m_textContainer.isDefaultWidth + "  Default Height:" + m_textContainer.isDefaultHeight);
                if (marginWidth == 0)
                    m_rectTransform.sizeDelta = new Vector2(m_preferredWidth + margins.x + margins.z, m_rectTransform.sizeDelta.y);

                if (marginHeight == 0)
                    m_rectTransform.sizeDelta = new Vector2(m_rectTransform.sizeDelta.x,  m_preferredHeight + margins.y + margins.w);

                
                Debug.Log("Auto-fitting Text. Default Width:" + m_preferredWidth + "  Default Height:" + m_preferredHeight);
                GenerateTextMesh();
                return;
            }
            */

            //for (int i = 0; i < m_lineNumber + 1; i++)
            //{
            //    Debug.Log("Line: " + (i + 1) + "  Character Count: " + m_textInfo.lineInfo[i].characterCount
            //                                 + "  Word Count: " + m_textInfo.lineInfo[i].wordCount
            //                                 + "  Space Count: " + m_textInfo.lineInfo[i].spaceCount
            //                                 + "  First: [" + m_textInfo.characterInfo[m_textInfo.lineInfo[i].firstCharacterIndex].character + "] at Index: " + m_textInfo.lineInfo[i].firstCharacterIndex
            //                                 + "  First Visible: [" + m_textInfo.characterInfo[m_textInfo.lineInfo[i].firstVisibleCharacterIndex].character + "] at Index: " + m_textInfo.lineInfo[i].firstVisibleCharacterIndex
            //                                 + "  Last [" + m_textInfo.characterInfo[m_textInfo.lineInfo[i].lastCharacterIndex].character + "] at Index: " + m_textInfo.lineInfo[i].lastCharacterIndex
            //                                 + "  Last visible [" + m_textInfo.characterInfo[m_textInfo.lineInfo[i].lastVisibleCharacterIndex].character + "] at Index: " + m_textInfo.lineInfo[i].lastVisibleCharacterIndex
            //                                 + "  Length: " + m_textInfo.lineInfo[i].lineLength
            //                                 + "  Line Extents: " + m_textInfo.lineInfo[i].lineExtents);
            //}

            //Debug.Log("Done rendering text. Character Count is " + m_textInfo.characterCount);
            //Debug.Log("Done rendering text. Preferred Width:" + m_preferredWidth + "  Preferred Height:" + m_preferredHeight);

            // Event indicating the text has been regenerated.
            TMPro_EventManager.ON_TEXT_CHANGED(this);

            //Debug.Log(m_minWidth);
            //Profiler.EndSample();
            //m_StopWatch.Stop();
            //Debug.Log("Done Rendering Text.");

            //Debug.Log("TimeElapsed is:" + (m_StopWatch.ElapsedTicks / 10000f).ToString("f4"));
            //m_StopWatch.Reset();
        }
        public void AddGlyphInfo(GlyphInfo[] glyphInfo)
        {
            m_glyphInfoList = new List<GlyphInfo>();
            m_characterSet = new int[m_fontInfo.CharacterCount];

            for (int i = 0; i < m_fontInfo.CharacterCount; i++)
            {
                //Debug.Log("Glyph Info   x:" + glyphInfo[i].x + "  y:" + glyphInfo[i].y + "  w:" + glyphInfo[i].width + "  h:" + glyphInfo[i].height);

                GlyphInfo g = new GlyphInfo();
                g.id = glyphInfo[i].id;
                g.x = glyphInfo[i].x;
                g.y = glyphInfo[i].y;
                g.width = glyphInfo[i].width;
                g.height = glyphInfo[i].height;
                g.xOffset = glyphInfo[i].xOffset;
                g.yOffset = (glyphInfo[i].yOffset) + m_fontInfo.Padding; // Padding added to keep baseline at Y = 0.
                g.xAdvance = glyphInfo[i].xAdvance;

                m_glyphInfoList.Add(g);

                // While iterating through list of glyphs, find the Descender & Ascender for this GlyphSet.
                //m_fontInfo.Ascender = Mathf.Max(m_fontInfo.Ascender, glyphInfo[i].yOffset);
                //m_fontInfo.Descender = Mathf.Min(m_fontInfo.Descender, glyphInfo[i].yOffset - glyphInfo[i].height);
                //Debug.Log(m_fontInfo.Ascender + "  " + m_fontInfo.Descender);
                m_characterSet[i] = g.id; // Add Character ID to Array to make it easier to get the kerning pairs.
            }

            // Sort List by ID.
            m_glyphInfoList = m_glyphInfoList.OrderBy(s => s.id).ToList();
        }
        public void ReadFontDefinition()
        {
            //Debug.Log("Reading Font Definition for " + this.name + ".");
            // Make sure that we have a Font Asset file assigned.
            if (m_fontInfo == null)
            {
                return;
            }

            // Create new instance of GlyphInfo Dictionary for fast access to glyph info.
            m_characterDictionary = new Dictionary<int, GlyphInfo>();
            foreach (GlyphInfo glyph in m_glyphInfoList)
            {
                if (!m_characterDictionary.ContainsKey(glyph.id))
                    m_characterDictionary.Add(glyph.id, glyph);
            }

            //Debug.Log("PRE: BaseLine:" + m_fontInfo.Baseline + "  Ascender:" + m_fontInfo.Ascender + "  Descender:" + m_fontInfo.Descender); // + "  Centerline:" + m_fontInfo.CenterLine);

            GlyphInfo temp_charInfo = new GlyphInfo();

            // Add Character (10) LineFeed, (13) Carriage Return & Space (32) to Dictionary if they don't exists.
            if (m_characterDictionary.ContainsKey(32))
            {
                m_characterDictionary[32].width = m_fontInfo.Ascender / 5;
                m_characterDictionary[32].height = m_fontInfo.Ascender - m_fontInfo.Descender;
                m_characterDictionary[32].yOffset= m_fontInfo.Ascender;
            }
            else
            {
                //Debug.Log("Adding Character 32 (Space) to Dictionary for Font (" + m_fontInfo.Name + ").");
                temp_charInfo = new GlyphInfo();
                temp_charInfo.id = 32;
                temp_charInfo.x = 0;
                temp_charInfo.y = 0;
                temp_charInfo.width = m_fontInfo.Ascender / 5;
                temp_charInfo.height = m_fontInfo.Ascender - m_fontInfo.Descender;
                temp_charInfo.xOffset = 0;
                temp_charInfo.yOffset = m_fontInfo.Ascender;
                temp_charInfo.xAdvance = m_fontInfo.PointSize / 4;
                m_characterDictionary.Add(32, temp_charInfo);
            }

            if (m_characterDictionary.ContainsKey(10) == false)
            {
                //Debug.Log("Adding Character 10 (Linefeed) to Dictionary for Font (" + m_fontInfo.Name + ").");

                temp_charInfo = new GlyphInfo();
                temp_charInfo.id = 10;
                temp_charInfo.x = 0; // m_characterDictionary[32].x;
                temp_charInfo.y = 0; // m_characterDictionary[32].y;
                temp_charInfo.width = 0; // m_characterDictionary[32].width;
                temp_charInfo.height = 0; // m_characterDictionary[32].height;
                temp_charInfo.xOffset = 0; // m_characterDictionary[32].xOffset;
                temp_charInfo.yOffset = 0; // m_characterDictionary[32].yOffset;
                temp_charInfo.xAdvance = 0;
                m_characterDictionary.Add(10, temp_charInfo);

                m_characterDictionary.Add(13, temp_charInfo);
            }

            // Add Tab Character to Dictionary. Tab is Tab Size * Space Character Width.
            if (m_characterDictionary.ContainsKey(9) == false)
            {
                //Debug.Log("Adding Character 9 (Tab) to Dictionary for Font (" + m_fontInfo.Name + ").");

                temp_charInfo = new GlyphInfo();
                temp_charInfo.id = 9;
                temp_charInfo.x = m_characterDictionary[32].x;
                temp_charInfo.y = m_characterDictionary[32].y;
                temp_charInfo.width = m_characterDictionary[32].width * TabSize;
                temp_charInfo.height = m_characterDictionary[32].height;
                temp_charInfo.xOffset = m_characterDictionary[32].xOffset;
                temp_charInfo.yOffset = m_characterDictionary[32].yOffset;
                temp_charInfo.xAdvance = m_characterDictionary[32].xAdvance * TabSize;
                m_characterDictionary.Add(9, temp_charInfo);
            }

            // Centerline is located at the center of character like { or in the middle of the lowercase o.
            //m_fontInfo.CenterLine = m_characterDictionary[111].yOffset - m_characterDictionary[111].height * 0.5f;

            // Tab Width is using the same xAdvance as space (32).
            m_fontInfo.TabWidth = m_characterDictionary[32].xAdvance;

            // Populate Dictionary with Kerning Information
            m_kerningDictionary = new Dictionary<int, KerningPair>();
            List<KerningPair> pairs = m_kerningInfo.kerningPairs;

            //Debug.Log(m_fontInfo.Name + " has " + pairs.Count +  " Kerning Pairs.");
            for (int i = 0; i < pairs.Count; i++)
            {
                KerningPair pair = pairs[i];
                KerningPairKey uniqueKey = new KerningPairKey(pair.AscII_Left, pair.AscII_Right);

                if (m_kerningDictionary.ContainsKey(uniqueKey.key) == false)
                    m_kerningDictionary.Add(uniqueKey.key, pair);
                else
                    Debug.Log("Kerning Key for [" + uniqueKey.ascii_Left + "] and [" + uniqueKey.ascii_Right + "] already exists.");
            }

            // Add Line Breaking Characters
            m_lineBreakingInfo = new LineBreakingTable();

            TextAsset leadingCharFile = Resources.Load("LineBreaking Leading Characters", typeof(TextAsset)) as TextAsset;
            if (leadingCharFile != null)
                m_lineBreakingInfo.leadingCharacters = GetCharacters(leadingCharFile);

            TextAsset followingCharFile = Resources.Load("LineBreaking Following Characters", typeof(TextAsset)) as TextAsset;
            if (followingCharFile != null)
                m_lineBreakingInfo.followingCharacters = GetCharacters(followingCharFile);

            // Compute Hashcode for the font asset name
            string fontName = this.name;
            fontHashCode = 0;
            for (int i = 0; i < fontName.Length; i++)
                fontHashCode = (fontHashCode << 5) - fontHashCode + fontName[i];

            // Compute Hashcode for the material name
            string materialName = material.name;
            materialHashCode = 0;
            for (int i = 0; i < materialName.Length; i++)
                materialHashCode = (materialHashCode << 5) - materialHashCode + materialName[i];
        }
Beispiel #6
0
        //private int loopCountB = 0;
        //private int loopCountC = 0;
        //private int loopCountD = 0;
        //private int loopCountE = 0;

       
        protected override void Awake()
        {
            //base.Awake();
            //Debug.Log("***** Awake() *****"); // on Object ID:" + GetInstanceID());      

            m_isAwake = true;      
            // Cache Reference to the Canvas
            m_canvas = GetComponentInParent(typeof(Canvas)) as Canvas;          

            // Cache Reference to RectTransform.
            m_rectTransform = gameObject.GetComponent<RectTransform>();
            if (m_rectTransform == null)   
                m_rectTransform = gameObject.AddComponent<RectTransform>();
            

                          
            // Cache a reference to the UIRenderer.
            m_uiRenderer = GetComponent<CanvasRenderer>();
            if (m_uiRenderer == null) 
				m_uiRenderer = gameObject.AddComponent<CanvasRenderer> ();

			//m_uiRenderer.hideFlags = HideFlags.HideInInspector;

            // Determine if the RectTransform is Driven         
            m_layoutController = GetComponent(typeof(ILayoutController)) as ILayoutController ?? (transform.parent != null ? transform.parent.GetComponent(typeof(ILayoutController)) as ILayoutController : null);           
            if (m_layoutController != null) IsRectTransformDriven = true;

            // Cache reference to Mask Component if one is present         
            //m_stencilID = MaterialManager.GetStencilID(gameObject);
            //m_mask = GetComponentInParent<Mask>();
                       

            // Load the font asset and assign material to renderer.
            LoadFontAsset();

            // Allocate our initial buffers.          
            m_char_buffer = new int[m_max_characters];           
            m_cached_GlyphInfo = new GlyphInfo();
            m_uiVertices = new UIVertex[0]; // 
            m_isFirstAllocation = true;          
            
            m_textInfo = new TMP_TextInfo();
            //m_textInfo.wordInfo = new List<TMP_WordInfo>();
            //m_textInfo.lineInfo = new TMP_LineInfo[m_max_numberOfLines];
            //m_textInfo.pageInfo = new TMP_PageInfo[16];
            //m_textInfo.meshInfo = new TMP_MeshInfo();
            //m_textInfo.meshInfo.meshArrays = new UIVertex[17][];
          

            // TODO : Add support for inline sprites and other fonts.
            m_fontAssetArray = new TextMeshProFont[16];
            
               
            // Check if we have a font asset assigned. Return if we don't because no one likes to see purple squares on screen.
            if (m_fontAsset == null)
            {
                Debug.LogWarning("Please assign a Font Asset to this " + transform.name + " gameobject.");
                return;
            }

            // Set Defaults for Font Auto-sizing
            if (m_fontSizeMin == 0) m_fontSizeMin = m_fontSize / 2;
            if (m_fontSizeMax == 0) m_fontSizeMax = m_fontSize * 2;

            //// Set flags to ensure our text is parsed and text re-drawn. 
            isInputParsingRequired = true;
            havePropertiesChanged = true;
            m_rectTransformDimensionsChanged = true;
            //m_isCalculateSizeRequired = true;

            ForceMeshUpdate(); // Added to force OnWillRenderObject() to be called in case object is not visible so we get initial bounds for the mesh.
        }
        //private int loopCountB;
        //private int loopCountC;
        //private int loopCountD;
        //private int loopCountE;


        void Awake()
        {
            //Debug.Log("Awake() called on Object ID " + GetInstanceID());
            
            // Code to handle Compatibility related to the switch from Color32 to Color
            if (m_fontColor == Color.white && m_fontColor32 != Color.white)
            {
                Debug.LogWarning("Converting Vertex Colors from Color32 to Color.", this);
                m_fontColor = m_fontColor32;
            } 
         
            m_textContainer = GetComponent<TextContainer>();
            if (m_textContainer == null)
                m_textContainer = gameObject.AddComponent<TextContainer>();

           
            // Cache Reference to the Mesh Renderer.
            m_renderer = GetComponent<Renderer>();
            if (m_renderer == null)
                m_renderer = gameObject.AddComponent<Renderer>();

           
            // Cache Reference to the transform;
            m_transform = gameObject.transform;

            // Cache a reference to the Mesh Filter.
            m_meshFilter = GetComponent<MeshFilter>();
            if (m_meshFilter == null)
                m_meshFilter = gameObject.AddComponent<MeshFilter>();


            // Cache a reference to our mesh.
            if (m_mesh == null)
            {
                //Debug.Log("Creating new mesh.");
                m_mesh = new Mesh();
                m_mesh.hideFlags = HideFlags.HideAndDontSave;

                m_meshFilter.mesh = m_mesh;
                //m_mesh.bounds = new Bounds(transform.position, new Vector3(1000, 1000, 0));
            }           
            m_meshFilter.hideFlags = HideFlags.HideInInspector;
         
            // Load the font asset and assign material to renderer.
            LoadFontAsset();

            // Allocate our initial buffers.
            m_char_buffer = new int[m_max_characters];
            //m_parsedCharacters = new char[m_max_characters];
            //m_lineExtents = new Mesh_Extents[m_max_numberOfLines];
            m_cached_GlyphInfo = new GlyphInfo();
            m_vertices = new Vector3[0]; // 
            m_isFirstAllocation = true;
            
            m_textInfo = new TMP_TextInfo();
            
            //m_fontAssetArray = new TextMeshProFont[16];


            // Check if we have a font asset assigned. Return if we don't because no one likes to see purple squares on screen.
            if (m_fontAsset == null)
            {
                Debug.LogWarning("Please assign a Font Asset to this " + transform.name + " gameobject.", this);
                return;
            }

            // Set Defaults for Font Auto-sizing
            if (m_fontSizeMin == 0) m_fontSizeMin = m_fontSize / 2;
            if (m_fontSizeMax == 0) m_fontSizeMax = m_fontSize * 2;

            //// Set flags to cause ensure our text is parsed and text redrawn. 
            isInputParsingRequired = true;
            m_havePropertiesChanged = true;

            ForceMeshUpdate(); // Added to force OnWillRenderObject() to be called in case object is not visible so we get initial bounds for the mesh.         
        }
        public void ReadFontDefinition()
        {
            //Debug.Log("Reading Font Definition for " + this.name + ".");
            // Make sure that we have a Font Asset file assigned.
            if (m_fontInfo == null)
            {
                return;
            }

            // Check Font Asset type
            //Debug.Log(name + "   " + fontAssetType);

            // Create new instance of GlyphInfo Dictionary for fast access to glyph info.
            m_characterDictionary = new Dictionary <int, GlyphInfo>();
            foreach (GlyphInfo glyph in m_glyphInfoList)
            {
                if (!m_characterDictionary.ContainsKey(glyph.id))
                {
                    m_characterDictionary.Add(glyph.id, glyph);
                }
            }


            //Debug.Log("PRE: BaseLine:" + m_fontInfo.Baseline + "  Ascender:" + m_fontInfo.Ascender + "  Descender:" + m_fontInfo.Descender); // + "  Centerline:" + m_fontInfo.CenterLine);

            GlyphInfo temp_charInfo = new GlyphInfo();

            // Add Character (10) LineFeed, (13) Carriage Return & Space (32) to Dictionary if they don't exists.
            if (m_characterDictionary.ContainsKey(32))
            {
                m_characterDictionary[32].width   = m_characterDictionary[32].xAdvance; // m_fontInfo.Ascender / 5;
                m_characterDictionary[32].height  = m_fontInfo.Ascender - m_fontInfo.Descender;
                m_characterDictionary[32].yOffset = m_fontInfo.Ascender;
            }
            else
            {
                //Debug.Log("Adding Character 32 (Space) to Dictionary for Font (" + m_fontInfo.Name + ").");
                temp_charInfo          = new GlyphInfo();
                temp_charInfo.id       = 32;
                temp_charInfo.x        = 0;
                temp_charInfo.y        = 0;
                temp_charInfo.width    = m_fontInfo.Ascender / 5;
                temp_charInfo.height   = m_fontInfo.Ascender - m_fontInfo.Descender;
                temp_charInfo.xOffset  = 0;
                temp_charInfo.yOffset  = m_fontInfo.Ascender;
                temp_charInfo.xAdvance = m_fontInfo.PointSize / 4;
                m_characterDictionary.Add(32, temp_charInfo);
            }

            // Add Non-Breaking Space (160)
            if (!m_characterDictionary.ContainsKey(160))
            {
                temp_charInfo = GlyphInfo.Clone(m_characterDictionary[32]);
                m_characterDictionary.Add(160, temp_charInfo);
            }


            if (m_characterDictionary.ContainsKey(10) == false)
            {
                //Debug.Log("Adding Character 10 (Linefeed) to Dictionary for Font (" + m_fontInfo.Name + ").");

                temp_charInfo          = new GlyphInfo();
                temp_charInfo.id       = 10;
                temp_charInfo.x        = 0; // m_characterDictionary[32].x;
                temp_charInfo.y        = 0; // m_characterDictionary[32].y;
                temp_charInfo.width    = 0; // m_characterDictionary[32].width;
                temp_charInfo.height   = 0; // m_characterDictionary[32].height;
                temp_charInfo.xOffset  = 0; // m_characterDictionary[32].xOffset;
                temp_charInfo.yOffset  = 0; // m_characterDictionary[32].yOffset;
                temp_charInfo.xAdvance = 0;
                m_characterDictionary.Add(10, temp_charInfo);

                m_characterDictionary.Add(13, temp_charInfo);
            }

            // Add Tab Character to Dictionary. Tab is Tab Size * Space Character Width.
            if (m_characterDictionary.ContainsKey(9) == false)
            {
                //Debug.Log("Adding Character 9 (Tab) to Dictionary for Font (" + m_fontInfo.Name + ").");

                temp_charInfo          = new GlyphInfo();
                temp_charInfo.id       = 9;
                temp_charInfo.x        = m_characterDictionary[32].x;
                temp_charInfo.y        = m_characterDictionary[32].y;
                temp_charInfo.width    = m_characterDictionary[32].width * TabSize + (m_characterDictionary[32].xAdvance - m_characterDictionary[32].width) * (TabSize - 1);
                temp_charInfo.height   = m_characterDictionary[32].height;
                temp_charInfo.xOffset  = m_characterDictionary[32].xOffset;
                temp_charInfo.yOffset  = m_characterDictionary[32].yOffset;
                temp_charInfo.xAdvance = m_characterDictionary[32].xAdvance * TabSize;
                m_characterDictionary.Add(9, temp_charInfo);
            }

            // Centerline is located at the center of character like { or in the middle of the lowercase o.
            //m_fontInfo.CenterLine = m_characterDictionary[111].yOffset - m_characterDictionary[111].height * 0.5f;

            // Tab Width is using the same xAdvance as space (32).
            m_fontInfo.TabWidth = m_characterDictionary[9].xAdvance;


            // Populate Dictionary with Kerning Information
            m_kerningDictionary = new Dictionary <int, KerningPair>();
            List <KerningPair> pairs = m_kerningInfo.kerningPairs;

            //Debug.Log(m_fontInfo.Name + " has " + pairs.Count +  " Kerning Pairs.");
            for (int i = 0; i < pairs.Count; i++)
            {
                KerningPair    pair      = pairs[i];
                KerningPairKey uniqueKey = new KerningPairKey(pair.AscII_Left, pair.AscII_Right);

                if (m_kerningDictionary.ContainsKey(uniqueKey.key) == false)
                {
                    m_kerningDictionary.Add(uniqueKey.key, pair);
                }
                else
                {
                    Debug.Log("Kerning Key for [" + uniqueKey.ascii_Left + "] and [" + uniqueKey.ascii_Right + "] already exists.");
                }
            }

            // Add Line Breaking Characters
            m_lineBreakingInfo = new LineBreakingTable();


            TextAsset leadingCharFile = Resources.Load("LineBreaking Leading Characters", typeof(TextAsset)) as TextAsset;

            if (leadingCharFile != null)
            {
                m_lineBreakingInfo.leadingCharacters = GetCharacters(leadingCharFile);
            }

            TextAsset followingCharFile = Resources.Load("LineBreaking Following Characters", typeof(TextAsset)) as TextAsset;

            if (followingCharFile != null)
            {
                m_lineBreakingInfo.followingCharacters = GetCharacters(followingCharFile);
            }


            // Compute Hashcode for the font asset name
            fontHashCode = TMP_TextUtilities.GetSimpleHashCode(this.name);

            // Compute Hashcode for the material name
            materialHashCode = TMP_TextUtilities.GetSimpleHashCode(material.name);
        }
Beispiel #9
0
        public void ReadFontDefinition()
        {
            //Debug.Log("Reading Font Definition for " + this.name + ".");
            // Make sure that we have a Font Asset file assigned.
            if (m_fontInfo == null)
            {
                return;
            }

            // Create new instance of GlyphInfo Dictionary for fast access to glyph info.
            m_characterDictionary = new Dictionary <int, GlyphInfo>();
            foreach (GlyphInfo glyph in m_glyphInfoList)
            {
                if (!m_characterDictionary.ContainsKey(glyph.id))
                {
                    m_characterDictionary.Add(glyph.id, glyph);
                }
            }


            //Debug.Log("PRE: BaseLine:" + m_fontInfo.Baseline + "  Ascender:" + m_fontInfo.Ascender + "  Descender:" + m_fontInfo.Descender); // + "  Centerline:" + m_fontInfo.CenterLine);

            GlyphInfo temp_charInfo = new GlyphInfo();

            // Add Character (10) LineFeed, (13) Carriage Return & Space (32) to Dictionary if they don't exists.
            m_characterDictionary.TryGetValue(10, out temp_charInfo);
            if (temp_charInfo == null)
            {
                // Modify Character [64] to create Char[32]
                if (m_characterDictionary.ContainsKey(32) == false)
                {
                    Debug.Log("Adding Character 32 (Space) to Dictionary for Font (" + m_fontInfo.Name + ").");

                    temp_charInfo          = new GlyphInfo();
                    temp_charInfo.id       = 32;
                    temp_charInfo.x        = 0;                        // m_characterDictionary[32].x;
                    temp_charInfo.y        = 0;                        // m_characterDictionary[32].y;
                    temp_charInfo.width    = 0;                        // m_characterDictionary[32].width;
                    temp_charInfo.height   = 0;                        // m_characterDictionary[32].height;
                    temp_charInfo.xOffset  = 0;                        // m_characterDictionary[32].xOffset;
                    temp_charInfo.yOffset  = 0;                        // m_characterDictionary[32].yOffset;
                    temp_charInfo.xAdvance = m_fontInfo.PointSize / 4; // m_characterDictionary[32].xAdvance;
                    m_characterDictionary.Add(32, temp_charInfo);

                    //m_characterDictionary.Add(13, temp_charInfo);
                }

                temp_charInfo          = new GlyphInfo();
                temp_charInfo.id       = 10;
                temp_charInfo.x        = m_characterDictionary[32].x;
                temp_charInfo.y        = m_characterDictionary[32].y;
                temp_charInfo.width    = m_characterDictionary[32].width;
                temp_charInfo.height   = m_characterDictionary[32].height;
                temp_charInfo.xOffset  = m_characterDictionary[32].xOffset;
                temp_charInfo.yOffset  = m_characterDictionary[32].yOffset;
                temp_charInfo.xAdvance = m_characterDictionary[32].xAdvance;
                m_characterDictionary.Add(10, temp_charInfo);

                m_characterDictionary.Add(13, temp_charInfo);
            }

            // Add Tab Character to Dictionary. Tab is Tab Size * Space Character Width.
            int tabSize = 10;

            temp_charInfo          = new GlyphInfo();
            temp_charInfo.id       = 9;
            temp_charInfo.x        = m_characterDictionary[32].x;
            temp_charInfo.y        = m_characterDictionary[32].y;
            temp_charInfo.width    = m_characterDictionary[32].width * tabSize;
            temp_charInfo.height   = m_characterDictionary[32].height;
            temp_charInfo.xOffset  = m_characterDictionary[32].xOffset;
            temp_charInfo.yOffset  = m_characterDictionary[32].yOffset;
            temp_charInfo.xAdvance = m_characterDictionary[32].xAdvance * tabSize;
            m_characterDictionary.Add(9, temp_charInfo);


            // Centerline is located at the center of character like { or in the middle of the lowercase o.
            //m_fontInfo.CenterLine = m_characterDictionary[111].yOffset - m_characterDictionary[111].height * 0.5f;

            // Tab Width is the same the xAdvance of the letter A. (Could change this to space 32).
            m_fontInfo.TabWidth = m_characterDictionary[65].xAdvance;


            // Populate Dictionary with Kerning Information
            m_kerningDictionary = new Dictionary <int, KerningPair>();
            List <KerningPair> pairs = m_kerningInfo.kerningPairs;

            //Debug.Log(m_fontInfo.Name + " has " + pairs.Count +  " Kerning Pairs.");

            for (int i = 0; i < pairs.Count; i++)
            {
                KerningPair    pair      = pairs[i];
                KerningPairKey uniqueKey = new KerningPairKey(pair.AscII_Left, pair.AscII_Right);

                if (m_kerningDictionary.ContainsKey(uniqueKey.key) == false)
                {
                    m_kerningDictionary.Add(uniqueKey.key, pair);
                }
                else
                {
                    Debug.Log("Kerning Key for [" + uniqueKey.ascii_Left + "] and [" + uniqueKey.ascii_Right + "] already exists.");
                }
            }
        }
Beispiel #10
0
        public void ReadFontDefinition()
        {
            //Debug.Log("Reading Font Definition for " + this.name + ".");
            // Make sure that we have a Font Asset file assigned.   
            if (m_fontInfo == null)
            {
                return;
            }

            // Create new instance of GlyphInfo Dictionary for fast access to glyph info.
            m_characterDictionary = new Dictionary<int, GlyphInfo>();
            foreach (GlyphInfo glyph in m_glyphInfoList)
            {
                if (!m_characterDictionary.ContainsKey(glyph.id))
                    m_characterDictionary.Add(glyph.id, glyph);
            }


            //Debug.Log("PRE: BaseLine:" + m_fontInfo.Baseline + "  Ascender:" + m_fontInfo.Ascender + "  Descender:" + m_fontInfo.Descender); // + "  Centerline:" + m_fontInfo.CenterLine);

            GlyphInfo temp_charInfo = new GlyphInfo();

            // Add Character (10) LineFeed, (13) Carriage Return & Space (32) to Dictionary if they don't exists.           
            m_characterDictionary.TryGetValue(10, out temp_charInfo);
            if (temp_charInfo == null)
            {
                // Modify Character [64] to create Char[32]
                if (m_characterDictionary.ContainsKey(32) == false)
                {
                    Debug.Log("Adding Character 32 (Space) to Dictionary for Font (" + m_fontInfo.Name + ").");

                    temp_charInfo = new GlyphInfo();
                    temp_charInfo.id = 32;
                    temp_charInfo.x = 0; // m_characterDictionary[32].x;
                    temp_charInfo.y = 0; // m_characterDictionary[32].y;
                    temp_charInfo.width = 0; // m_characterDictionary[32].width;
                    temp_charInfo.height = 0; // m_characterDictionary[32].height;
                    temp_charInfo.xOffset = 0; // m_characterDictionary[32].xOffset;
                    temp_charInfo.yOffset = 0; // m_characterDictionary[32].yOffset;
                    temp_charInfo.xAdvance = m_fontInfo.PointSize / 4; // m_characterDictionary[32].xAdvance;
                    m_characterDictionary.Add(32, temp_charInfo);

                    //m_characterDictionary.Add(13, temp_charInfo);
                }

                temp_charInfo = new GlyphInfo();
                temp_charInfo.id = 10;
                temp_charInfo.x = m_characterDictionary[32].x;
                temp_charInfo.y = m_characterDictionary[32].y;
                temp_charInfo.width = m_characterDictionary[32].width;
                temp_charInfo.height = m_characterDictionary[32].height;
                temp_charInfo.xOffset = m_characterDictionary[32].xOffset;
                temp_charInfo.yOffset = m_characterDictionary[32].yOffset;
                temp_charInfo.xAdvance = m_characterDictionary[32].xAdvance;
                m_characterDictionary.Add(10, temp_charInfo);

                m_characterDictionary.Add(13, temp_charInfo);
            }

            // Add Tab Character to Dictionary. Tab is Tab Size * Space Character Width.
            int tabSize = 10;

            temp_charInfo = new GlyphInfo();
            temp_charInfo.id = 9;
            temp_charInfo.x = m_characterDictionary[32].x;
            temp_charInfo.y = m_characterDictionary[32].y;
            temp_charInfo.width = m_characterDictionary[32].width * tabSize;
            temp_charInfo.height = m_characterDictionary[32].height;
            temp_charInfo.xOffset = m_characterDictionary[32].xOffset;
            temp_charInfo.yOffset = m_characterDictionary[32].yOffset;
            temp_charInfo.xAdvance = m_characterDictionary[32].xAdvance * tabSize;
            m_characterDictionary.Add(9, temp_charInfo);


            // Centerline is located at the center of character like { or in the middle of the lowercase o.
            //m_fontInfo.CenterLine = m_characterDictionary[111].yOffset - m_characterDictionary[111].height * 0.5f;

            // Tab Width is the same the xAdvance of the letter A. (Could change this to space 32).
            m_fontInfo.TabWidth = m_characterDictionary[65].xAdvance;


            // Populate Dictionary with Kerning Information
            m_kerningDictionary = new Dictionary<int, KerningPair>();
            List<KerningPair> pairs = m_kerningInfo.kerningPairs;

            //Debug.Log(m_fontInfo.Name + " has " + pairs.Count +  " Kerning Pairs.");

            for (int i = 0; i < pairs.Count; i++)
            {
                KerningPair pair = pairs[i];
                KerningPairKey uniqueKey = new KerningPairKey(pair.AscII_Left, pair.AscII_Right);

                if (m_kerningDictionary.ContainsKey(uniqueKey.key) == false)
                    m_kerningDictionary.Add(uniqueKey.key, pair);
                else
                    Debug.Log("Kerning Key for [" + uniqueKey.ascii_Left + "] and [" + uniqueKey.ascii_Right + "] already exists.");
            }
        }
Beispiel #11
0
 public void ReadFontDefinition()
 {
     if (this.m_fontInfo != null)
     {
         this.m_characterDictionary = new Dictionary <int, GlyphInfo>();
         foreach (GlyphInfo info in this.m_glyphInfoList)
         {
             if (!this.m_characterDictionary.ContainsKey(info.id))
             {
                 this.m_characterDictionary.Add(info.id, info);
             }
         }
         GlyphInfo info2 = new GlyphInfo();
         if (this.m_characterDictionary.ContainsKey(0x20))
         {
             this.m_characterDictionary[0x20].width   = this.m_fontInfo.Ascender / 5f;
             this.m_characterDictionary[0x20].height  = this.m_fontInfo.Ascender - this.m_fontInfo.Descender;
             this.m_characterDictionary[0x20].yOffset = this.m_fontInfo.Ascender;
         }
         else
         {
             info2 = new GlyphInfo {
                 id       = 0x20,
                 x        = 0f,
                 y        = 0f,
                 width    = this.m_fontInfo.Ascender / 5f,
                 height   = this.m_fontInfo.Ascender - this.m_fontInfo.Descender,
                 xOffset  = 0f,
                 yOffset  = this.m_fontInfo.Ascender,
                 xAdvance = this.m_fontInfo.PointSize / 4f
             };
             this.m_characterDictionary.Add(0x20, info2);
         }
         if (!this.m_characterDictionary.ContainsKey(10))
         {
             info2 = new GlyphInfo {
                 id       = 10,
                 x        = 0f,
                 y        = 0f,
                 width    = 0f,
                 height   = 0f,
                 xOffset  = 0f,
                 yOffset  = 0f,
                 xAdvance = 0f
             };
             this.m_characterDictionary.Add(10, info2);
             this.m_characterDictionary.Add(13, info2);
         }
         if (!this.m_characterDictionary.ContainsKey(9))
         {
             info2 = new GlyphInfo {
                 id       = 9,
                 x        = this.m_characterDictionary[0x20].x,
                 y        = this.m_characterDictionary[0x20].y,
                 width    = this.m_characterDictionary[0x20].width * this.TabSize,
                 height   = this.m_characterDictionary[0x20].height,
                 xOffset  = this.m_characterDictionary[0x20].xOffset,
                 yOffset  = this.m_characterDictionary[0x20].yOffset,
                 xAdvance = this.m_characterDictionary[0x20].xAdvance * this.TabSize
             };
             this.m_characterDictionary.Add(9, info2);
         }
         this.m_fontInfo.TabWidth = this.m_characterDictionary[0x20].xAdvance;
         this.m_kerningDictionary = new Dictionary <int, KerningPair>();
         List <KerningPair> kerningPairs = this.m_kerningInfo.kerningPairs;
         for (int i = 0; i < kerningPairs.Count; i++)
         {
             KerningPair    pair = kerningPairs[i];
             KerningPairKey key  = new KerningPairKey(pair.AscII_Left, pair.AscII_Right);
             if (!this.m_kerningDictionary.ContainsKey(key.key))
             {
                 this.m_kerningDictionary.Add(key.key, pair);
             }
             else
             {
                 Debug.Log(string.Concat(new object[] { "Kerning Key for [", key.ascii_Left, "] and [", key.ascii_Right, "] already exists." }));
             }
         }
         this.m_lineBreakingInfo = new LineBreakingTable();
         TextAsset file = Resources.Load("LineBreaking Leading Characters", typeof(TextAsset)) as TextAsset;
         if (file != null)
         {
             this.m_lineBreakingInfo.leadingCharacters = this.GetCharacters(file);
         }
         TextAsset asset2 = Resources.Load("LineBreaking Following Characters", typeof(TextAsset)) as TextAsset;
         if (asset2 != null)
         {
             this.m_lineBreakingInfo.followingCharacters = this.GetCharacters(asset2);
         }
         string name = base.name;
         this.fontHashCode = 0;
         for (int j = 0; j < name.Length; j++)
         {
             this.fontHashCode = ((this.fontHashCode << 5) - this.fontHashCode) + name[j];
         }
         string str2 = this.material.name;
         this.materialHashCode = 0;
         for (int k = 0; k < str2.Length; k++)
         {
             this.materialHashCode = ((this.materialHashCode << 5) - this.materialHashCode) + str2[k];
         }
     }
 }
Beispiel #12
0
 public void ReadFontDefinition()
 {
     if (m_fontInfo != null)
     {
         m_characterDictionary = new Dictionary <int, GlyphInfo>();
         foreach (GlyphInfo glyphInfo2 in m_glyphInfoList)
         {
             if (!m_characterDictionary.ContainsKey(glyphInfo2.id))
             {
                 m_characterDictionary.Add(glyphInfo2.id, glyphInfo2);
             }
         }
         GlyphInfo glyphInfo = new GlyphInfo();
         if (m_characterDictionary.ContainsKey(32))
         {
             m_characterDictionary[32].width   = m_characterDictionary[32].xAdvance;
             m_characterDictionary[32].height  = m_fontInfo.Ascender - m_fontInfo.Descender;
             m_characterDictionary[32].yOffset = m_fontInfo.Ascender;
         }
         else
         {
             glyphInfo          = new GlyphInfo();
             glyphInfo.id       = 32;
             glyphInfo.x        = 0f;
             glyphInfo.y        = 0f;
             glyphInfo.width    = m_fontInfo.Ascender / 5f;
             glyphInfo.height   = m_fontInfo.Ascender - m_fontInfo.Descender;
             glyphInfo.xOffset  = 0f;
             glyphInfo.yOffset  = m_fontInfo.Ascender;
             glyphInfo.xAdvance = m_fontInfo.PointSize / 4f;
             m_characterDictionary.Add(32, glyphInfo);
         }
         if (!m_characterDictionary.ContainsKey(160))
         {
             glyphInfo = GlyphInfo.Clone(m_characterDictionary[32]);
             m_characterDictionary.Add(160, glyphInfo);
         }
         if (!m_characterDictionary.ContainsKey(10))
         {
             glyphInfo          = new GlyphInfo();
             glyphInfo.id       = 10;
             glyphInfo.x        = 0f;
             glyphInfo.y        = 0f;
             glyphInfo.width    = 10f;
             glyphInfo.height   = m_characterDictionary[32].height;
             glyphInfo.xOffset  = 0f;
             glyphInfo.yOffset  = m_characterDictionary[32].yOffset;
             glyphInfo.xAdvance = 0f;
             m_characterDictionary.Add(10, glyphInfo);
             if (!m_characterDictionary.ContainsKey(13))
             {
                 m_characterDictionary.Add(13, glyphInfo);
             }
         }
         if (!m_characterDictionary.ContainsKey(9))
         {
             glyphInfo          = new GlyphInfo();
             glyphInfo.id       = 9;
             glyphInfo.x        = m_characterDictionary[32].x;
             glyphInfo.y        = m_characterDictionary[32].y;
             glyphInfo.width    = m_characterDictionary[32].width * (float)(int)TabSize + (m_characterDictionary[32].xAdvance - m_characterDictionary[32].width) * (float)(TabSize - 1);
             glyphInfo.height   = m_characterDictionary[32].height;
             glyphInfo.xOffset  = m_characterDictionary[32].xOffset;
             glyphInfo.yOffset  = m_characterDictionary[32].yOffset;
             glyphInfo.xAdvance = m_characterDictionary[32].xAdvance * (float)(int)TabSize;
             m_characterDictionary.Add(9, glyphInfo);
         }
         m_fontInfo.TabWidth = m_characterDictionary[9].xAdvance;
         m_kerningDictionary = new Dictionary <int, KerningPair>();
         List <KerningPair> kerningPairs = m_kerningInfo.kerningPairs;
         for (int i = 0; i < kerningPairs.Count; i++)
         {
             KerningPair    kerningPair    = kerningPairs[i];
             KerningPairKey kerningPairKey = new KerningPairKey(kerningPair.AscII_Left, kerningPair.AscII_Right);
             if (!m_kerningDictionary.ContainsKey(kerningPairKey.key))
             {
                 m_kerningDictionary.Add(kerningPairKey.key, kerningPair);
             }
             else
             {
                 Debug.Log("Kerning Key for [" + kerningPairKey.ascii_Left + "] and [" + kerningPairKey.ascii_Right + "] already exists.");
             }
         }
         m_lineBreakingInfo = new LineBreakingTable();
         TextAsset textAsset = Resources.Load("LineBreaking Leading Characters", typeof(TextAsset)) as TextAsset;
         if (textAsset != null)
         {
             m_lineBreakingInfo.leadingCharacters = GetCharacters(textAsset);
         }
         TextAsset textAsset2 = Resources.Load("LineBreaking Following Characters", typeof(TextAsset)) as TextAsset;
         if (textAsset2 != null)
         {
             m_lineBreakingInfo.followingCharacters = GetCharacters(textAsset2);
         }
         fontHashCode     = TMP_TextUtilities.GetSimpleHashCode(base.name);
         materialHashCode = TMP_TextUtilities.GetSimpleHashCode(material.name);
     }
 }
Beispiel #13
0
        public void ReadFontDefinition()
        {
            if (this.m_fontInfo == null)
            {
                return;
            }
            this.m_characterDictionary = new Dictionary <int, GlyphInfo>();
            using (List <GlyphInfo> .Enumerator enumerator = this.m_glyphInfoList.GetEnumerator())
            {
                while (enumerator.MoveNext())
                {
                    GlyphInfo current = enumerator.get_Current();
                    if (!this.m_characterDictionary.ContainsKey(current.id))
                    {
                        this.m_characterDictionary.Add(current.id, current);
                    }
                }
            }
            GlyphInfo glyphInfo = new GlyphInfo();

            if (this.m_characterDictionary.ContainsKey(32))
            {
                this.m_characterDictionary.get_Item(32).width   = this.m_fontInfo.Ascender / 5f;
                this.m_characterDictionary.get_Item(32).height  = this.m_fontInfo.Ascender - this.m_fontInfo.Descender;
                this.m_characterDictionary.get_Item(32).yOffset = this.m_fontInfo.Ascender;
            }
            else
            {
                glyphInfo          = new GlyphInfo();
                glyphInfo.id       = 32;
                glyphInfo.x        = 0f;
                glyphInfo.y        = 0f;
                glyphInfo.width    = this.m_fontInfo.Ascender / 5f;
                glyphInfo.height   = this.m_fontInfo.Ascender - this.m_fontInfo.Descender;
                glyphInfo.xOffset  = 0f;
                glyphInfo.yOffset  = this.m_fontInfo.Ascender;
                glyphInfo.xAdvance = this.m_fontInfo.PointSize / 4f;
                this.m_characterDictionary.Add(32, glyphInfo);
            }
            if (!this.m_characterDictionary.ContainsKey(10))
            {
                glyphInfo          = new GlyphInfo();
                glyphInfo.id       = 10;
                glyphInfo.x        = 0f;
                glyphInfo.y        = 0f;
                glyphInfo.width    = 0f;
                glyphInfo.height   = 0f;
                glyphInfo.xOffset  = 0f;
                glyphInfo.yOffset  = 0f;
                glyphInfo.xAdvance = 0f;
                this.m_characterDictionary.Add(10, glyphInfo);
                this.m_characterDictionary.Add(13, glyphInfo);
            }
            if (!this.m_characterDictionary.ContainsKey(9))
            {
                glyphInfo          = new GlyphInfo();
                glyphInfo.id       = 9;
                glyphInfo.x        = this.m_characterDictionary.get_Item(32).x;
                glyphInfo.y        = this.m_characterDictionary.get_Item(32).y;
                glyphInfo.width    = this.m_characterDictionary.get_Item(32).width *(float)this.TabSize;
                glyphInfo.height   = this.m_characterDictionary.get_Item(32).height;
                glyphInfo.xOffset  = this.m_characterDictionary.get_Item(32).xOffset;
                glyphInfo.yOffset  = this.m_characterDictionary.get_Item(32).yOffset;
                glyphInfo.xAdvance = this.m_characterDictionary.get_Item(32).xAdvance *(float)this.TabSize;
                this.m_characterDictionary.Add(9, glyphInfo);
            }
            this.m_fontInfo.TabWidth = this.m_characterDictionary.get_Item(32).xAdvance;
            this.m_kerningDictionary = new Dictionary <int, KerningPair>();
            List <KerningPair> kerningPairs = this.m_kerningInfo.kerningPairs;

            for (int i = 0; i < kerningPairs.get_Count(); i++)
            {
                KerningPair    kerningPair    = kerningPairs.get_Item(i);
                KerningPairKey kerningPairKey = new KerningPairKey(kerningPair.AscII_Left, kerningPair.AscII_Right);
                if (!this.m_kerningDictionary.ContainsKey(kerningPairKey.key))
                {
                    this.m_kerningDictionary.Add(kerningPairKey.key, kerningPair);
                }
                else
                {
                    Debug.Log(string.Concat(new object[]
                    {
                        "Kerning Key for [",
                        kerningPairKey.ascii_Left,
                        "] and [",
                        kerningPairKey.ascii_Right,
                        "] already exists."
                    }));
                }
            }
            this.m_lineBreakingInfo = new LineBreakingTable();
            TextAsset textAsset = Resources.Load("LineBreaking Leading Characters", typeof(TextAsset)) as TextAsset;

            if (textAsset != null)
            {
                this.m_lineBreakingInfo.leadingCharacters = this.GetCharacters(textAsset);
            }
            TextAsset textAsset2 = Resources.Load("LineBreaking Following Characters", typeof(TextAsset)) as TextAsset;

            if (textAsset2 != null)
            {
                this.m_lineBreakingInfo.followingCharacters = this.GetCharacters(textAsset2);
            }
            string name = base.name;

            this.fontHashCode = 0;
            for (int j = 0; j < name.get_Length(); j++)
            {
                this.fontHashCode = (this.fontHashCode << 5) - this.fontHashCode + (int)name.get_Chars(j);
            }
            string name2 = this.material.name;

            this.materialHashCode = 0;
            for (int k = 0; k < name2.get_Length(); k++)
            {
                this.materialHashCode = (this.materialHashCode << 5) - this.materialHashCode + (int)name2.get_Chars(k);
            }
        }
Beispiel #14
0
        void Awake()
        {
            //Debug.Log("TextMeshPro OnEnable() has been called. HavePropertiesChanged = " + havePropertiesChanged); // has been called on Object ID:" + gameObject.GetInstanceID());      
      
            // Get Reference to AdvancedLayoutComponent if one is attached.
            m_advancedLayoutComponent = GetComponent<TMPro_AdvancedLayout>();
            //isAdvancedLayoutComponentPresent = m_advancedLayoutComponent == null ? false : true;

            // Reset max line lenght
            max_LineWrapLength = 999;

            // Cache Reference to the Mesh Renderer.
            m_renderer = renderer;
            m_renderer.sortingLayerID = m_sortingLayerID;
            m_renderer.sortingOrder = m_sortingOrder; 
        

            // Cache Reference to the transform;
            m_transform = transform;

            // Cache a reference to the Mesh Filter.
            m_meshFilter = GetComponent<MeshFilter>();
            if (m_meshFilter == null)
                m_meshFilter = gameObject.AddComponent<MeshFilter>();

            // Cache a reference to our mesh.
            if (m_mesh == null)
            {
                //Debug.Log("Creating new mesh."); 
                m_mesh = new Mesh();
                m_mesh.hideFlags = HideFlags.HideAndDontSave;

                m_meshFilter.mesh = m_mesh;                
                //m_mesh.bounds = new Bounds(transform.position, new Vector3(1000, 1000, 0));               
            }           
            m_meshFilter.hideFlags = HideFlags.HideInInspector;
                      
            // Load the font asset and assign material to renderer.
            LoadFontAsset();

            // Allocate our initial buffers.          
            m_char_buffer = new int[m_max_characters];
            //m_lineExtents = new Mesh_Extents[m_max_numberOfLines];
            m_cached_GlyphInfo = new GlyphInfo();
            m_vertices = new Vector3[0]; // 
            m_isFirstAllocation = true;          
            m_textInfo = new TextInfo();
            m_fontAssetArray = new TextMeshProFont[16];
            m_textInfo.lineInfo = new LineInfo[m_max_numberOfLines];
            m_textInfo.meshInfo = new TMPro_MeshInfo();      
         

            // Check if we have a font asset assigned. Return if we don't because no one likes to see purple squares on screen.
            if (m_fontAsset == null)
            {
                Debug.LogWarning("Please assign a Font Asset to this " + transform.name + " gameobject.");
                return;
            }

            //// Set flags to cause ensure our text is parsed and text redrawn. 
            isInputParsingRequired = true;
            havePropertiesChanged = true;
            
            ForceMeshUpdate(); // Added to force OnWillRenderObject() to be called in case object is not visible so we get initial bounds for the mesh.
            ///* ScheduleUpdate();         
        }
Beispiel #15
0
        public void DrawMesh()
        {
            TMP_MeshInfo meshInfo = m_textMeshProComponent.textInfo.meshInfo;
            TMP_TextInfo textInfo = m_textMeshProComponent.textInfo;

            TMP_CharacterInfo[] characterInfo = textInfo.characterInfo;
            int characterCount = textInfo.characterCount;

            Vector3[] vertices     = meshInfo.vertices;
            Vector2[] uv0s         = meshInfo.uv0s;
            Vector2[] uv2s         = meshInfo.uv2s;
            Color32[] vertexColors = meshInfo.vertexColors;
            Vector3[] normals      = meshInfo.normals;
            Vector4[] tangents     = meshInfo.tangents;
            float     num          = 1f;
            float     num2         = 0f;
            float     num3         = 0f;

            for (int i = 0; i < characterCount; i++)
            {
                char      character   = characterInfo[i].character;
                GlyphInfo glyphInfo   = m_textMeshProComponent.font.characterDictionary[character];
                int       vertexIndex = characterInfo[i].vertexIndex;
                if (characterInfo[i].isVisible)
                {
                    float   x = (characterInfo[i].bottomLeft.x + characterInfo[i].topRight.x) / 2f;
                    Vector3 a = new Vector3(x, 0f, 0f);
                    vertices[vertexIndex]     += -a;
                    vertices[vertexIndex + 1] += -a;
                    vertices[vertexIndex + 2] += -a;
                    vertices[vertexIndex + 3] += -a;
                    float time = (characterCount <= 1) ? 0f : ((float)i / (float)(characterCount - 1));
                    num2 = ScaleCurve.Evaluate(time);
                    Matrix4x4 matrix4x = Matrix4x4.TRS(new Vector3(0f, 0f, 0f), Quaternion.Euler(0f, 0f, 0f), new Vector3(num2, num2, 1f));
                    vertices[vertexIndex]     = matrix4x.MultiplyPoint3x4(vertices[vertexIndex]);
                    vertices[vertexIndex + 1] = matrix4x.MultiplyPoint3x4(vertices[vertexIndex + 1]);
                    vertices[vertexIndex + 2] = matrix4x.MultiplyPoint3x4(vertices[vertexIndex + 2]);
                    vertices[vertexIndex + 3] = matrix4x.MultiplyPoint3x4(vertices[vertexIndex + 3]);
                    float num4 = glyphInfo.xOffset * characterInfo[i].scale * num2 + (characterInfo[i].topRight.x - characterInfo[i].bottomLeft.x) / 2f * num2;
                    a = new Vector3(num4 + num3, 0f, 0f);
                    vertices[vertexIndex]     += a;
                    vertices[vertexIndex + 1] += a;
                    vertices[vertexIndex + 2] += a;
                    vertices[vertexIndex + 3] += a;
                    uv2s[vertexIndex].y       *= num2;
                    uv2s[vertexIndex + 1].y   *= num2;
                    uv2s[vertexIndex + 2].y   *= num2;
                    uv2s[vertexIndex + 3].y   *= num2;
                }
                num3 += glyphInfo.xAdvance * characterInfo[i].scale * num2 + m_textMeshProComponent.characterSpacing;
            }
            int   vertexIndex2 = characterInfo[characterCount - 1].vertexIndex;
            float x2           = vertices[0].x;
            float x3           = vertices[vertexIndex2 + 2].x;

            for (int j = 0; j < characterCount; j++)
            {
                int vertexIndex3 = characterInfo[j].vertexIndex;
                if (characterInfo[j].isVisible)
                {
                    float   num5   = (vertices[vertexIndex3].x + vertices[vertexIndex3 + 2].x) / 2f;
                    Vector3 vector = new Vector3(num5, 0f, 0f);
                    vertices[vertexIndex3]     += -vector;
                    vertices[vertexIndex3 + 1] += -vector;
                    vertices[vertexIndex3 + 2] += -vector;
                    vertices[vertexIndex3 + 3] += -vector;
                    float   num6 = (num5 - x2) / (x3 - x2);
                    float   num7 = num6 + 0.0001f;
                    float   num8 = TranslationCurve.Evaluate(num6) * num;
                    float   num9 = TranslationCurve.Evaluate(num7) * num;
                    Vector3 lhs  = new Vector3(1f, 0f, 0f);
                    Debug.DrawLine(end: new Vector3(0f - (num9 - num8), num7 * (x3 - x2) + x2 - num5, 0f), start: new Vector3(num5, num8, 0f), color: Color.green, duration: 60f);
                    Vector3   rhs      = new Vector3(num7 * (x3 - x2) + x2, num9) - new Vector3(num5, num8);
                    float     num10    = Mathf.Acos(Vector3.Dot(lhs, rhs.normalized)) * 57.29578f;
                    Vector3   vector2  = Vector3.Cross(lhs, rhs);
                    float     z        = (!(vector2.z > 0f)) ? (360f - num10) : num10;
                    Matrix4x4 matrix4x = Matrix4x4.TRS(new Vector3(0f, num8, 0f), Quaternion.Euler(0f, 0f, z), new Vector3(1f, 1f, 1f));
                    vertices[vertexIndex3]      = matrix4x.MultiplyPoint3x4(vertices[vertexIndex3]);
                    vertices[vertexIndex3 + 1]  = matrix4x.MultiplyPoint3x4(vertices[vertexIndex3 + 1]);
                    vertices[vertexIndex3 + 2]  = matrix4x.MultiplyPoint3x4(vertices[vertexIndex3 + 2]);
                    vertices[vertexIndex3 + 3]  = matrix4x.MultiplyPoint3x4(vertices[vertexIndex3 + 3]);
                    vertices[vertexIndex3]     += vector;
                    vertices[vertexIndex3 + 1] += vector;
                    vertices[vertexIndex3 + 2] += vector;
                    vertices[vertexIndex3 + 3] += vector;
                }
            }
            Mesh mesh = m_textMeshProComponent.mesh;

            mesh.vertices = vertices;
            mesh.uv       = uv0s;
            mesh.uv2      = uv2s;
            mesh.colors32 = vertexColors;
            if (m_sharedMaterial.HasProperty(ShaderUtilities.ID_Shininess))
            {
                mesh.normals  = normals;
                mesh.tangents = tangents;
            }
            mesh.RecalculateBounds();
        }
 public void ReadFontDefinition()
 {
     if (m_fontInfo != null)
     {
         m_characterDictionary = new Dictionary <int, GlyphInfo>();
         foreach (GlyphInfo glyphInfo2 in m_glyphInfoList)
         {
             if (!m_characterDictionary.ContainsKey(glyphInfo2.id))
             {
                 m_characterDictionary.Add(glyphInfo2.id, glyphInfo2);
             }
         }
         GlyphInfo glyphInfo = new GlyphInfo();
         if (m_characterDictionary.ContainsKey(32))
         {
             m_characterDictionary[32].width   = m_fontInfo.Ascender / 5f;
             m_characterDictionary[32].height  = m_fontInfo.Ascender - m_fontInfo.Descender;
             m_characterDictionary[32].yOffset = m_fontInfo.Ascender;
         }
         else
         {
             glyphInfo          = new GlyphInfo();
             glyphInfo.id       = 32;
             glyphInfo.x        = 0f;
             glyphInfo.y        = 0f;
             glyphInfo.width    = m_fontInfo.Ascender / 5f;
             glyphInfo.height   = m_fontInfo.Ascender - m_fontInfo.Descender;
             glyphInfo.xOffset  = 0f;
             glyphInfo.yOffset  = m_fontInfo.Ascender;
             glyphInfo.xAdvance = m_fontInfo.PointSize / 4f;
             m_characterDictionary.Add(32, glyphInfo);
         }
         if (!m_characterDictionary.ContainsKey(10))
         {
             glyphInfo          = new GlyphInfo();
             glyphInfo.id       = 10;
             glyphInfo.x        = 0f;
             glyphInfo.y        = 0f;
             glyphInfo.width    = 0f;
             glyphInfo.height   = 0f;
             glyphInfo.xOffset  = 0f;
             glyphInfo.yOffset  = 0f;
             glyphInfo.xAdvance = 0f;
             m_characterDictionary.Add(10, glyphInfo);
             m_characterDictionary.Add(13, glyphInfo);
         }
         int num = 10;
         if (!m_characterDictionary.ContainsKey(9))
         {
             glyphInfo          = new GlyphInfo();
             glyphInfo.id       = 9;
             glyphInfo.x        = m_characterDictionary[32].x;
             glyphInfo.y        = m_characterDictionary[32].y;
             glyphInfo.width    = m_characterDictionary[32].width * (float)num;
             glyphInfo.height   = m_characterDictionary[32].height;
             glyphInfo.xOffset  = m_characterDictionary[32].xOffset;
             glyphInfo.yOffset  = m_characterDictionary[32].yOffset;
             glyphInfo.xAdvance = m_characterDictionary[32].xAdvance * (float)num;
             m_characterDictionary.Add(9, glyphInfo);
         }
         m_fontInfo.TabWidth = m_characterDictionary[32].xAdvance;
         m_kerningDictionary = new Dictionary <int, KerningPair>();
         List <KerningPair> kerningPairs = m_kerningInfo.kerningPairs;
         for (int i = 0; i < kerningPairs.Count; i++)
         {
             KerningPair    kerningPair    = kerningPairs[i];
             KerningPairKey kerningPairKey = new KerningPairKey(kerningPair.AscII_Left, kerningPair.AscII_Right);
             if (!m_kerningDictionary.ContainsKey(kerningPairKey.key))
             {
                 m_kerningDictionary.Add(kerningPairKey.key, kerningPair);
             }
             else
             {
                 Debug.Log("Kerning Key for [" + kerningPairKey.ascii_Left + "] and [" + kerningPairKey.ascii_Right + "] already exists.");
             }
         }
         m_lineBreakingInfo = new LineBreakingTable();
         TextAsset textAsset = Resources.Load("LineBreaking Leading Characters", typeof(TextAsset)) as TextAsset;
         if (textAsset != null)
         {
             m_lineBreakingInfo.leadingCharacters = GetCharacters(textAsset);
         }
         TextAsset textAsset2 = Resources.Load("LineBreaking Following Characters", typeof(TextAsset)) as TextAsset;
         if (textAsset2 != null)
         {
             m_lineBreakingInfo.followingCharacters = GetCharacters(textAsset2);
         }
         string name = base.name;
         fontHashCode = 0;
         for (int j = 0; j < name.Length; j++)
         {
             fontHashCode = (fontHashCode << 5) - fontHashCode + name[j];
         }
         string name2 = material.name;
         materialHashCode = 0;
         for (int k = 0; k < name2.Length; k++)
         {
             materialHashCode = (materialHashCode << 5) - materialHashCode + name2[k];
         }
     }
 }