int Render_Character(byte[] buffer_fill, byte[] buffer_edge, int buffer_width, int buffer_height, int offset, int asc, FaceStyles style, float thickness, RenderModes rasterMode, ref FT_GlyphInfo glyphInfo);
// 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) { 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); // 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); } // 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)); fontAsset.AddGlyphInfo(ConvertToGlyphs(fontGlyphInfo)); var fontTexture = CreateFontTexture(atlasWidth, atlasHeight, textureBuffer, fontRenderMode); fontTexture.name = outputFilename + " Atlas"; fontTexture.hideFlags = HideFlags.HideInHierarchy; fontAsset.atlas = fontTexture; AssetDatabase.AddObjectToAsset(fontTexture, fontAsset); // Find all Materials referencing this font atlas. Material[] materialReferences = TMP_EditorUtility.FindMaterialReferences(fontAsset).Where(m => m != null).ToArray(); if (materialReferences == null || materialReferences.Length <= 0) { // Create new Material and add it as Sub-Asset Shader shader = Shader.Find("TMPro/Distance Field"); Material fontMaterial = new Material(shader); fontMaterial.name = outputFilename + " Material"; fontAsset.material = fontMaterial; fontMaterial.hideFlags = HideFlags.HideInHierarchy; AssetDatabase.AddObjectToAsset(fontMaterial, fontAsset); materialReferences = new 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); }
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); }