Exemple #1
0
        public static void CreateSDFAsset(TexAsset asset, Font font, string fontPath)
        {
            // initialize
            CheckErr(TMPro_FontPlugin.Initialize_FontEngine());
            CheckErr(TMPro_FontPlugin.Load_TrueType_Font(fontPath));
            CheckErr(TMPro_FontPlugin.FT_Size_Font(72));

            _buffers = new byte[_bufferWidth * _bufferHeight];
            var charSet = new int[asset.chars.Length];

            _glyphsInfo = new FT_GlyphInfo[asset.chars.Length];
            _atlasInfo  = null;

            for (int i = 0; i < asset.chars.Length; i++)
            {
                charSet[i] = asset.chars[i].characterIndex;
            }

            float strokeSize = _styleStrokeSize;

            if (_render == RenderModes.DistanceField16)
            {
                strokeSize = _styleStrokeSize * 16;
            }
            if (_render == RenderModes.DistanceField32)
            {
                strokeSize = _styleStrokeSize * 32;
            }

            ThreadPool.QueueUserWorkItem(SomeTask =>
            {
                try
                {
                    onRendering = true;

                    CheckErr(TMPro_FontPlugin.Render_Characters(_buffers, _bufferWidth, _bufferHeight, _padding,
                                                                charSet, charSet.Length, _style, strokeSize, true, _render, _optimized ? 4 : 0,
                                                                ref _faceInfo, _glyphsInfo));

                    EditorApplication.delayCall += delegate()
                    {
                        try
                        {
                            OnFinished(Convert(asset));
                        }
                        catch (Exception ex)
                        {
                            Debug.LogException(ex);
                            Debug.LogWarningFormat("Failed to create SDF File for {0}.ttf. Consider delete and rerender again", asset.id);
                        }
                        finally
                        {
                            hasRendered = false;
                            onRendering = false;
                            if (onRenderingBatch > 0)
                            {
                                isRenderingBatchFinished = true;
                            }
                        }
                    };
                    Debug.LogFormat("Font Rendering of {0}.ttf has completed.", asset.id);
                }
                catch (Exception ex)
                {
                    Debug.LogException(ex);
                    Debug.LogWarningFormat("Failed to create Render {0}.ttf. Consider rerender again", asset.id);
                }
                finally
                {
                    onRendering = false;
                }
            });
        }
        // PRAGMA MARK - Public Interface
        public static void Bake(Font font, bool useAutoSizing, int fontSize, int characterPadding, TMPFontPackingModes fontPackingMode, int atlasWidth, int atlasHeight, FaceStyles fontStyle, int fontStyleMod, RenderModes fontRenderMode, string charactersToBake, string outputFilePath, TMPFont.GlyphOverride[] glyphOverrides)
        {
            int errorCode = TMPro_FontPlugin.Initialize_FontEngine();

            if (errorCode != 0 && errorCode != 99)               // 99 means that engine was already initialized
            {
                Debug.LogWarning("Error Code: " + errorCode + "  occurred while initializing TMPro_FontPlugin.");
                return;
            }


            string fontPath = AssetDatabase.GetAssetPath(font);

            errorCode = TMPro_FontPlugin.Load_TrueType_Font(fontPath);
            if (errorCode != 0 && errorCode != 99)               // 99 means that font was already loaded
            {
                Debug.LogWarning("Error Code: " + errorCode + "  occurred while loading font: " + font + ".");
                return;
            }

            if (useAutoSizing)
            {
                fontSize = 72;
            }
            errorCode = TMPro_FontPlugin.FT_Size_Font(fontSize);
            if (errorCode != 0)
            {
                Debug.LogWarning("Error Code: " + errorCode + "  occurred while sizing font: " + font + " to size: " + fontSize + ".");
                return;
            }

            byte[] textureBuffer = new byte[atlasWidth * atlasHeight];

            int[] characterArray = charactersToBake.Select(c => (int)c).ToArray();
            int   characterCount = charactersToBake.Length;

            var fontFaceInfo  = new FT_FaceInfo();
            var fontGlyphInfo = new FT_GlyphInfo[characterCount];

            float strokeSize = fontStyleMod;

            if (fontRenderMode == RenderModes.DistanceField16)
            {
                strokeSize *= 16;
            }
            else if (fontRenderMode == RenderModes.DistanceField32)
            {
                strokeSize *= 32;
            }

            errorCode = TMPro_FontPlugin.Render_Characters(textureBuffer, atlasWidth, atlasHeight, characterPadding, characterArray, characterCount, fontStyle, strokeSize, useAutoSizing, fontRenderMode, (int)fontPackingMode, ref fontFaceInfo, fontGlyphInfo);
            if (errorCode != 0)
            {
                Debug.LogWarning("Error Code: " + errorCode + "  occurred while rendering font characters!");
                return;
            }

            string outputFilename = Path.GetFileNameWithoutExtension(outputFilePath);

            List <Material> materialReferences = new List <Material>();

            // check if font asset already exists
            TMP_FontAsset fontAsset = AssetDatabase.LoadAssetAtPath(outputFilePath, typeof(TMP_FontAsset)) as TMP_FontAsset;

            if (fontAsset == null)
            {
                fontAsset = ScriptableObject.CreateInstance <TMP_FontAsset>();                // Create new TextMeshPro Font Asset.
                AssetDatabase.CreateAsset(fontAsset, outputFilePath);
            }
            else
            {
                // Find materials using font atlas as main texture (needed for material presets)
                materialReferences = FindAssetsByType <Material>()
                                     .Where(a => a.mainTexture != null && a.mainTexture.Equals(fontAsset.atlas))
                                     .ToList();
            }


            // Destroy Assets that will be replaced.
            UnityEngine.Object.DestroyImmediate(fontAsset.atlas, allowDestroyingAssets: true);

            fontAsset.fontAssetType = (fontRenderMode >= RenderModes.DistanceField16) ? TMP_FontAsset.FontAssetTypes.SDF : TMP_FontAsset.FontAssetTypes.Bitmap;

            fontAsset.AddFaceInfo(ConvertToFaceInfo(fontFaceInfo));

            // Apply glyph overrides
            var glyphs = ConvertToGlyphs(fontGlyphInfo);

            foreach (var glyphOverride in glyphOverrides)
            {
                var glyph = glyphs.FirstOrDefault(a => a.id == glyphOverride.id);
                glyph.width    = glyphOverride.W;
                glyph.height   = glyphOverride.H;
                glyph.xOffset  = glyphOverride.OX;
                glyph.yOffset  = glyphOverride.OY;
                glyph.xAdvance = glyphOverride.ADV;
                glyph.scale    = glyphOverride.SF;
            }
            fontAsset.AddGlyphInfo(glyphs);

            var fontTexture = CreateFontTexture(atlasWidth, atlasHeight, textureBuffer, fontRenderMode);

            fontTexture.name      = outputFilename + " Atlas";
            fontTexture.hideFlags = HideFlags.HideInHierarchy;

            fontAsset.atlas = fontTexture;
            AssetDatabase.AddObjectToAsset(fontTexture, fontAsset);


            // Find all remaining Materials referencing this font atlas.
            materialReferences.AddRange(TMP_EditorUtility.FindMaterialReferences(fontAsset)
                                        .Where(m => m != null)
                                        .ToList());
            materialReferences = materialReferences.Distinct().ToList();


            if (materialReferences == null || materialReferences.Count <= 0)
            {
                // Create new Material and add it as Sub-Asset
                Shader   shader       = Shader.Find("TextMeshPro/Distance Field");
                Material fontMaterial = new Material(shader);
                fontMaterial.name = outputFilename + " Material";

                fontAsset.material     = fontMaterial;
                fontMaterial.hideFlags = HideFlags.HideInHierarchy;
                AssetDatabase.AddObjectToAsset(fontMaterial, fontAsset);

                materialReferences = new List <Material> {
                    fontMaterial
                };
            }
            foreach (var m in materialReferences)
            {
                m.SetTexture(ShaderUtilities.ID_MainTex, fontTexture);
                m.SetFloat(ShaderUtilities.ID_TextureWidth, fontTexture.width);
                m.SetFloat(ShaderUtilities.ID_TextureHeight, fontTexture.height);


                m.SetFloat(ShaderUtilities.ID_WeightNormal, fontAsset.normalStyle);
                m.SetFloat(ShaderUtilities.ID_WeightBold, fontAsset.boldStyle);

                m.SetFloat(ShaderUtilities.ID_GradientScale, characterPadding + 1);
            }

            AssetDatabase.SaveAssets();
            // Re-import font asset to get the new updated version.
            AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(fontAsset));
            fontAsset.ReadFontDefinition();
            AssetDatabase.Refresh();

            // NEED TO GENERATE AN EVENT TO FORCE A REDRAW OF ANY TEXTMESHPRO INSTANCES THAT MIGHT BE USING THIS FONT ASSET
            TMPro_EventManager.ON_FONT_PROPERTY_CHANGED(true, fontAsset);
        }
Exemple #3
0
    private void GenerateFontAtlasButton()
    {
        if (!m_IsProcessing && m_SourceFontFile != null)
        {
            DestroyImmediate(m_FontAtlas);
            m_FontAtlas      = null;
            m_OutputFeedback = string.Empty;
            m_SavedFontAtlas = null;
            int errorCode;

            errorCode = TMPro_FontPlugin.Initialize_FontEngine(); // Initialize Font Engine
            if (errorCode != 0)
            {
                if (errorCode == 0xF0)
                {
                    //Debug.Log("Font Library was already initialized!");
                    errorCode = 0;
                }
                else
                {
                    Debug.Log("Error Code: " + errorCode + "  occurred while Initializing the FreeType Library.");
                }
            }

            string fontPath = AssetDatabase.GetAssetPath(m_SourceFontFile); // Get file path of TTF Font.

            if (errorCode == 0)
            {
                errorCode = TMPro_FontPlugin.Load_TrueType_Font(fontPath); // Load the selected font.

                if (errorCode != 0)
                {
                    if (errorCode == 0xF1)
                    {
                        //Debug.Log("Font was already loaded!");
                        errorCode = 0;
                    }
                    else
                    {
                        Debug.Log("Error Code: " + errorCode + "  occurred while Loading the [" + m_SourceFontFile.name + "] font file. This typically results from the use of an incompatible or corrupted font file.");
                    }
                }
            }

            if (errorCode == 0)
            {
                if (m_PointSizeSamplingMode == 0)
                {
                    m_PointSize = 72;                                   // If Auto set size to 72 pts.
                }
                errorCode = TMPro_FontPlugin.FT_Size_Font(m_PointSize); // Load the selected font and size it accordingly.
                if (errorCode != 0)
                {
                    Debug.Log("Error Code: " + errorCode + "  occurred while Sizing the font.");
                }
            }

            // Define an array containing the characters we will render.
            if (errorCode == 0)
            {
                int[] characterSet;
                if (m_CharacterSetSelectionMode == 7 || m_CharacterSetSelectionMode == 8)
                {
                    List <int> charList = new List <int>();

                    for (int i = 0; i < m_CharacterSequence.Length; i++)
                    {
                        // Check to make sure we don't include duplicates
                        if (charList.FindIndex(item => item == m_CharacterSequence[i]) == -1)
                        {
                            charList.Add(m_CharacterSequence[i]);
                        }
                        else
                        {
                            //Debug.Log("Character [" + characterSequence[i] + "] is a duplicate.");
                        }
                    }

                    characterSet = charList.ToArray();
                }
                else if (m_CharacterSetSelectionMode == 6)
                {
                    characterSet = ParseHexNumberSequence(m_CharacterSequence);
                }
                else
                {
                    characterSet = ParseNumberSequence(m_CharacterSequence);
                }

                m_CharacterCount = characterSet.Length;

                m_TextureBuffer = new byte[m_AtlasWidth * m_AtlasHeight];

                m_FontFaceInfo = new FT_FaceInfo();

                m_FontGlyphInfo = new FT_GlyphInfo[m_CharacterCount];

                int padding = m_Padding;

                bool autoSizing = m_PointSizeSamplingMode == 0;

                float strokeSize = m_FontStyleValue;
                if (m_RenderMode == RenderModes.DistanceField16)
                {
                    strokeSize = m_FontStyleValue * 16;
                }
                if (m_RenderMode == RenderModes.DistanceField32)
                {
                    strokeSize = m_FontStyleValue * 32;
                }

                m_IsProcessing          = true;
                m_IsGenerationCancelled = false;

                // Start Stop Watch
                m_StopWatch = System.Diagnostics.Stopwatch.StartNew();

                ThreadPool.QueueUserWorkItem(someTask =>
                {
                    m_IsRenderingDone = false;

                    errorCode = TMPro_FontPlugin.Render_Characters(m_TextureBuffer, m_AtlasWidth, m_AtlasHeight,
                                                                   padding, characterSet, m_CharacterCount, m_FontStyle, strokeSize, autoSizing, m_RenderMode,
                                                                   (int)m_PackingMode, ref m_FontFaceInfo, m_FontGlyphInfo);

                    ThreadRenderBackupFont(0, m_AtlasWidth);

                    m_IsRenderingDone = true;
                });
            }
        }
    }
Exemple #4
0
    private void ThreadRenderBackupFont(int backupLevel, int xOffsetDist)
    {
        if (m_FontBackupPaths == null || m_FontBackupPaths.Length <= backupLevel)
        {
            return;
        }

        List <int> list = new List <int>();

        for (int index = 0; index < m_CharacterCount; ++index)
        {
            if (m_FontGlyphInfo[index].x == -1)
            {
                list.Add(m_FontGlyphInfo[index].id);
            }
        }

        // 如果有指定字体,则在这里插入
        if (m_CharacterUseFontBackup != null && m_CharacterUseFontBackup.Length > backupLevel)
        {
            foreach (var character in m_CharacterUseFontBackup[backupLevel])
            {
                if (!string.IsNullOrEmpty(character))
                {
                    for (int i = 0; i < character.Length; i++)
                    {
                        // Check to make sure we don't include duplicates
                        if (list.FindIndex(item => item == character[i]) == -1)
                        {
                            list.Add(character[i]);
                        }
                    }
                }
            }
        }

        if (list.Count == 0)
        {
            return;
        }

        int[]  characterSet = list.ToArray();
        string fontPath     = m_FontBackupPaths[backupLevel];
        int    errorCode    = TMPro_FontPlugin.Load_TrueType_Font(fontPath);

        if (errorCode != 0)
        {
            return;
        }

        var tmpAtlasWidth     = 512;
        var tmpAtlasHeight    = 512;
        var tmpTextureBuffer  = new byte[tmpAtlasWidth * tmpAtlasHeight];
        var tmpCharacterCount = characterSet.Length;
        var tmpFontFaceInfo   = default(FT_FaceInfo);
        var tmpFontGlyphInfo  = new FT_GlyphInfo[tmpCharacterCount];

        bool  autoSizing = m_PointSizeSamplingMode == 0;
        float strokeSize = m_FontStyleValue;

        if (m_RenderMode == RenderModes.DistanceField16)
        {
            strokeSize = m_FontStyleValue * 16;
        }
        if (m_RenderMode == RenderModes.DistanceField32)
        {
            strokeSize = m_FontStyleValue * 32;
        }

        errorCode = TMPro_FontPlugin.Render_Characters(tmpTextureBuffer, tmpAtlasWidth,
                                                       tmpAtlasHeight, m_Padding, characterSet, tmpCharacterCount, m_FontStyle, strokeSize,
                                                       autoSizing, m_RenderMode, (int)m_PackingMode, ref tmpFontFaceInfo, tmpFontGlyphInfo);
        if (errorCode != 0)
        {
            return;
        }

        int wordWidth = m_PointSize;
        int xStart    = xOffsetDist - m_Padding * 2 - wordWidth; // 从padding开始拷贝,否则会出现负偏移丢失的情况
        int yStart    = m_AtlasHeight - m_Padding - 1;
        int numY      = 0;

        for (int index = 0; index < tmpCharacterCount; ++index)
        {
            if (!Mathf.Approximately(tmpFontGlyphInfo[index].x, -1))
            {
                var gi = tmpFontGlyphInfo[index];
                var x  = Mathf.FloorToInt(gi.x) - m_Padding;
                var y  = tmpAtlasHeight - (Mathf.FloorToInt(gi.y) - m_Padding);
                var w  = Mathf.CeilToInt(gi.width) + m_Padding * 2;
                var h  = Mathf.CeilToInt(gi.height) + m_Padding * 2;

                for (int r = 0; r < h; r++)
                {
                    for (int c = 0; c < w; c++)
                    {
                        m_TextureBuffer[(yStart - r) * m_AtlasWidth + c + xStart] =
                            tmpTextureBuffer[(y - r) * tmpAtlasWidth + c + x];
                    }
                }
                var idx = ArrayUtility.FindIndex(m_FontGlyphInfo, info => info.id == gi.id);
                if (idx == -1)
                {
                    // 往数组里面添加
                    ArrayUtility.Add(ref m_FontGlyphInfo, new FT_GlyphInfo()
                    {
                        id = gi.id
                    });
                    idx = m_FontGlyphInfo.Length - 1;
                }

                var gi2 = m_FontGlyphInfo[idx];
                gi2.x                = xStart + m_Padding;
                gi2.y                = m_AtlasHeight - yStart + m_Padding;
                gi2.width            = gi.width;
                gi2.height           = gi.height;
                gi2.xAdvance         = gi.xAdvance;
                gi2.xOffset          = gi.xOffset;
                gi2.yOffset          = gi.yOffset;
                m_FontGlyphInfo[idx] = gi2;

                yStart = yStart - h - m_Padding - 1;
                numY++;

                // 如果超过五个则换一列
                if (numY > 5)
                {
                    numY   = 0;
                    xStart = xStart - m_Padding * 2 - wordWidth;
                    yStart = m_AtlasHeight - m_Padding - 1;
                }
            }
        }

        ThreadRenderBackupFont(++backupLevel, xStart);
    }
        public static void CreateSDFAsset(TexFont font, string fontPath)
        {
            // Simple checks...
            if (!font.Font_Asset)
            {
                return;
            }
            // Expensive check, somewhat useless

            /*var objs = AssetDatabase.FindAssets("t:TMP_FontAsset");
             * foreach (var obj in objs)
             * {
             *  var asset = AssetDatabase.LoadAssetAtPath<TMP_FontAsset>(AssetDatabase.GUIDToAssetPath(obj));
             *  if (asset.name == font.name)
             *  {
             *      font.SDF_Asset = asset;
             *      return;
             *  }
             * }*/

            //TMPro_FontPlugin.LinkDebugLog();

            var error = 0;

            error = TMPro_FontPlugin.Initialize_FontEngine();
            if (error != 0 && error != 99)
            {
                throw new Exception("ERROR: " + error.ToString());
            }
            error = TMPro_FontPlugin.Load_TrueType_Font(fontPath);
            if (error != 0 && error != 99)
            {
                throw new Exception("ERROR: " + error.ToString());
            }
            error = TMPro_FontPlugin.FT_Size_Font(72);
            if (error != 0 && error != 99)
            {
                throw new Exception("ERROR: " + error.ToString());
            }

            _buffers = new byte[_bufferWidth * _bufferHeight];
            var charSet = new int[font.chars.Length];

            _glyphsInfo = new FT_GlyphInfo[font.chars.Length];
            _atlasInfo  = null;

            for (int i = 0; i < font.chars.Length; i++)
            {
                charSet[i] = font.chars[i].characterIndex;
            }
            float strokeSize = _styleStrokeSize;

            if (_render == RenderModes.DistanceField16)
            {
                strokeSize = _styleStrokeSize * 16;
            }
            if (_render == RenderModes.DistanceField32)
            {
                strokeSize = _styleStrokeSize * 32;
            }

            EditorApplication.update += OnUpdate;

            _renderedFont = font;
            ThreadPool.QueueUserWorkItem(SomeTask =>
            {
                onRendering = true;

                error = TMPro_FontPlugin.Render_Characters(_buffers, _bufferWidth, _bufferHeight, _padding,
                                                           charSet, charSet.Length, _style, strokeSize, true, _render, _optimized ? 4 : 0,
                                                           ref _faceInfo, _glyphsInfo);

                if (error != 0 && error != 99)
                {
                    onRendering = false;
                    throw new Exception("ERROR: " + error.ToString());
                }
                // Can't call OnFinished here because this isn't a Main thread
                hasRendered = true;

                Debug.LogFormat("Font Rendering of {0}.ttf is completed.", font.id);
            });
        }