// Convert from FT_FaceInfo to FaceInfo private static FaceInfo ConvertToFaceInfo(FT_FaceInfo ftFace) { FaceInfo face = new FaceInfo(); face.Name = ftFace.name; face.PointSize = (float)ftFace.pointSize; face.Padding = ftFace.padding; face.LineHeight = ftFace.lineHeight; face.Baseline = 0; face.Ascender = ftFace.ascender; face.Descender = ftFace.descender; face.CenterLine = ftFace.centerLine; face.Underline = ftFace.underline; face.UnderlineThickness = ftFace.underlineThickness == 0 ? 5 : ftFace.underlineThickness; // Set Thickness to 5 if TTF value is Zero. face.SuperscriptOffset = face.Ascender; face.SubscriptOffset = face.Underline; face.SubSize = 0.5f; //face.CharacterCount = ftFace.characterCount; face.AtlasWidth = ftFace.atlasWidth; face.AtlasHeight = ftFace.atlasHeight; if (face.strikethrough == 0) { face.strikethrough = face.CapHeight / 2.5f; } return(face); }
// Convert from FT_FaceInfo to FaceInfo private static FaceInfo GetFaceInfo(FT_FaceInfo ftFace, int scaleFactor) { var face = new FaceInfo(); face.Name = ftFace.name; face.PointSize = ( float )ftFace.pointSize / scaleFactor; face.Padding = ( float )ftFace.padding / scaleFactor; face.LineHeight = ftFace.lineHeight / scaleFactor; face.CapHeight = 0; face.Baseline = 0; face.Ascender = ftFace.ascender / scaleFactor; face.Descender = ftFace.descender / scaleFactor; face.CenterLine = ftFace.centerLine / scaleFactor; face.Underline = ftFace.underline / scaleFactor; face.UnderlineThickness = ftFace.underlineThickness == 0 ? 5 : ftFace.underlineThickness / scaleFactor; // Set Thickness to 5 if TTF value is Zero. face.strikethrough = (face.Ascender + face.Descender) / 2.75f; face.strikethroughThickness = face.UnderlineThickness; face.SuperscriptOffset = face.Ascender; face.SubscriptOffset = face.Underline; face.SubSize = 0.5f; face.AtlasWidth = ftFace.atlasWidth / scaleFactor; face.AtlasHeight = ftFace.atlasHeight / scaleFactor; return(face); }
static void CreateTexture(int channel) { renderCompleted = false; textureChannel = channel; int charStartIndex = 0; for (int i = 0; i < channel; i++) { charStartIndex += charCounts[i]; } charCount = charCounts[channel]; charCodes = new int[charCount]; for (int i = 0; i < charCount; i++) { charCodes[i] = gbkChars[charStartIndex + i]; } faceInfo = new FT_FaceInfo(); glyphInfo = new FT_GlyphInfo[charCount]; textureBuffer = new byte[textureSize * textureSize]; ThreadPool.QueueUserWorkItem(SomeTask => { TMPro_FontPlugin.Render_Characters(textureBuffer, textureSize, textureSize, charPadding, charCodes, charCount, FaceStyles.Normal, 32, false, RenderModes.DistanceField16, 0, ref faceInfo, glyphInfo); renderCompleted = true; }); }
// 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); }
//============================================================================== // 関数 //============================================================================== public void Start(TMP_FontAssetUpdaterSettings settings, Action onComplete = null) { ShaderUtilities.GetShaderPropertyIDs(); m_settings = settings; m_font = settings.SourceFontFile; m_fontAssetPath = AssetDatabase.GetAssetPath(settings.FontAsset); var fontPath = AssetDatabase.GetAssetPath(m_font); var fontName = Path.GetFileNameWithoutExtension(fontPath); var filter = "t:TMP_FontAsset " + fontName + " SDF"; m_assets = AssetDatabase .FindAssets(filter, new [] { "Assets" }) .Select(c => AssetDatabase.GUIDToAssetPath(c)) .ToArray() ; m_characterSequence = m_settings.CustomCharacterList.text; if (m_font == null) { return; } GameObject.DestroyImmediate(m_fontAtlas); m_fontAtlas = null; var initResult = TMPro_FontPlugin.Initialize_FontEngine(); if (initResult != 0 && initResult != 0xF0) { Debug.Log("Error Code: " + initResult + " occurred while Initializing the FreeType Library."); return; } var loadResult = TMPro_FontPlugin.Load_TrueType_Font(fontPath); if (loadResult != 0 && loadResult != 0xF1) { Debug.Log("Error Code: " + loadResult + " occurred while Loading the [" + m_font.name + "] font file. This typically results from the use of an incompatible or corrupted font file."); return; } var sizeResult = TMPro_FontPlugin.FT_Size_Font(SamplingPointSize); if (sizeResult != 0) { Debug.Log("Error Code: " + sizeResult + " occurred while Sizing the font."); return; } int[] characterSet; var charList = new List <int>(); for (int i = 0; i < m_characterSequence.Length; i++) { 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(); m_characterCount = characterSet.Length; m_textureBuffer = new byte[AtlasWidth * AtlasHeight]; m_fontFaceInfo = new FT_FaceInfo(); m_fontGlyphInfo = new FT_GlyphInfo[m_characterCount]; int padding = Padding; var autoSizing = SamplingPointSizeMode == SamplingPointSizes.AutoSizing; var strokeSize = FontStyleModifier; if (RenderMode == RenderModes.DistanceField16) { strokeSize = FontStyleModifier * 16; } if (RenderMode == RenderModes.DistanceField32) { strokeSize = FontStyleModifier * 32; } EditorApplication.update += OnUpdate; ThreadPool.QueueUserWorkItem(_ => { TMPro_FontPlugin.Render_Characters ( buffer: m_textureBuffer, buffer_width: AtlasWidth, buffer_height: AtlasHeight, character_padding: padding, asc_set: characterSet, char_count: m_characterCount, style: FontStyle, style_mod: strokeSize, autoSize: autoSizing, renderMode: RenderMode, method: ( int )PackingMethod, fontData: ref m_fontFaceInfo, Output: m_fontGlyphInfo ); EditorApplication.delayCall += () => { OnDone(); if (onComplete != null) { onComplete(); } }; }); }
int Render_Characters(byte[] buffer, int buffer_width, int buffer_height, int character_padding, int[] asc_set, int char_count, FaceStyles style, float style_mod, bool autoSize, RenderModes renderMode, int method, ref FT_FaceInfo fontData, FT_GlyphInfo[] Output);
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; }); } } }