static KerningTable GetKerningTable(string fontFilePath, int pointSize) { KerningTable kerningInfo = new KerningTable(); kerningInfo.kerningPairs = new List <KerningPair>(); // Temporary Array to hold the kerning pairs from the Native Plug-in. FT_KerningPair[] kerningPairs = new FT_KerningPair[7500]; int kpCount = TMPro_FontPlugin.FT_GetKerningPairs(fontFilePath, m_kerningSet, m_kerningSet.Length, kerningPairs); for (int i = 0; i < kpCount; i++) { // Proceed to add each kerning pairs. KerningPair kp = new KerningPair((uint)kerningPairs[i].ascII_Left, (uint)kerningPairs[i].ascII_Right, kerningPairs[i].xAdvanceOffset * pointSize); // Filter kerning pairs to avoid duplicates int index = kerningInfo.kerningPairs.FindIndex(item => item.firstGlyph == kp.firstGlyph && item.secondGlyph == kp.secondGlyph); if (index == -1) { kerningInfo.kerningPairs.Add(kp); } else if (!TMP_Settings.warningsDisabled) { Debug.LogWarning("Kerning Key for [" + kp.firstGlyph + "] and [" + kp.secondGlyph + "] is a duplicate."); } } return(kerningInfo); }
private void OnDone() { EditorUtility.ClearProgressBar(); EditorApplication.update -= OnUpdate; UpdateRenderFeedbackWindow(); CreateFontTexture(); foreach (var asset in m_assets) { Save_SDF_FontAsset(asset); } m_fontAtlas = null; TMPro_FontPlugin.Destroy_FontEngine(); if (m_fontAtlas != null && EditorUtility.IsPersistent(m_fontAtlas) == false) { GameObject.DestroyImmediate(m_fontAtlas); } Resources.UnloadUnusedAssets(); }
private void OnUpdate() { var info = m_fontAssetPath; var progress = TMPro_FontPlugin.Check_RenderProgress(); EditorUtility.DisplayProgressBar("TMP_FontAssetUpdater", info, progress); }
private void MyUpdate() { if (m_IsRepaintNeeded) { //Debug.Log("Repainting..."); m_IsRepaintNeeded = false; Repaint(); } // 第一步创建字体渲染数组 // Update Progress bar is we are Rendering a Font. if (m_IsProcessing) { m_RenderingProgress = TMPro_FontPlugin.Check_RenderProgress(); m_FontAssetInfos[m_CurGenerateIndex].genPercent = m_RenderingProgress * 100; m_IsRepaintNeeded = true; } // Update Feedback Window & Create Font Texture once Rendering is done. if (m_IsRenderingDone) { // Stop StopWatch m_StopWatch.Stop(); Debug.Log("Font Atlas generation completed in: " + m_StopWatch.Elapsed.TotalMilliseconds.ToString("0.000 ms.")); m_StopWatch.Reset(); m_IsProcessing = false; m_IsRenderingDone = false; if (m_IsGenerationCancelled == false) { // 第二步输出渲染结果 UpdateRenderFeedbackWindow(); // 第三步将渲染数组填充到纹理贴图(注意,贴图共享不删除) CreateFontTexture(); foreach (var asset in m_FontAssetInfos[m_CurGenerateIndex].assets) { // 最后保存信息到字体资产 Save_SDF_FontAsset(asset); } // 最后置空 m_FontAtlas = null; } Repaint(); } }
public void OnDisable() { //Debug.Log("TextMeshPro Editor Window has been disabled."); // Destroy Engine only if it has been initialized already TMPro_FontPlugin.Destroy_FontEngine(); if (m_FontAtlas != null && EditorUtility.IsPersistent(m_FontAtlas) == false) { //Debug.Log("Destroying font_Atlas!"); DestroyImmediate(m_FontAtlas); } if (File.Exists("Assets/TextMesh Pro/Glyph Report.txt")) { File.Delete("Assets/TextMesh Pro/Glyph Report.txt"); File.Delete("Assets/TextMesh Pro/Glyph Report.txt.meta"); AssetDatabase.Refresh(); } Resources.UnloadUnusedAssets(); }
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; }); }
static void CreateFont() { InitGBK(); string path = AssetDatabase.GetAssetPath(Selection.activeObject); fontName = Path.GetFileNameWithoutExtension(path); int errorCode = TMPro_FontPlugin.Initialize_FontEngine(); if (errorCode == 0 || errorCode == 99) { errorCode = TMPro_FontPlugin.Load_TrueType_Font(path); if (errorCode == 0 || errorCode == 99) { errorCode = TMPro_FontPlugin.FT_Size_Font(fontSize); if (errorCode == 0 || errorCode == 99) { EditorApplication.update += RenderUpdate; textureColors = new Color32[textureSize * textureSize]; charInfoList = new List <CharacterInfo>(); CreateTexture(0); } } } }
public static void SetupGUI(TexAsset asset) { EditorGUI.BeginDisabledGroup(onRendering); GUILayout.BeginHorizontal(); GUI.changed = false; GUILayout.Label("Atlas Resolution", GUILayout.Width(EditorGUIUtility.labelWidth)); _bufferWidth = EditorGUILayout.IntPopup(_bufferWidth, FontResolutionLabels, FontAtlasResolutions); //, GUILayout.Width(80)); _bufferHeight = EditorGUILayout.IntPopup(_bufferHeight, FontResolutionLabels, FontAtlasResolutions); //, GUILayout.Width(80)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label("Padding", GUILayout.Width(EditorGUIUtility.labelWidth)); _padding = EditorGUILayout.IntSlider(_padding, 1, 10); GUILayout.EndHorizontal(); _render = (RenderModes)EditorGUILayout.EnumPopup(_render); if (GUILayout.Button("Render")) { CreateSDFAsset(asset); } EditorGUI.BeginDisabledGroup(onRendering || asset.type != TexAssetType.FontSigned); GUI.backgroundColor = Color.red; if (GUILayout.Button("Delete SDF Asset")) { AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(((TexFontSigned)asset).asset)); asset = Deconvert((TexFontSigned)asset); } GUI.backgroundColor = Color.white; EditorGUI.EndDisabledGroup(); { EditorGUILayout.Space(); if (GUILayout.Button("Render All Fonts")) { onRenderingBatch = (EditorUtility.DisplayDialogComplex("Confirm Action", "Are you sure? This will take few moments.\nAnd what will you do with existing SDF Asset?", "Overwrite", "Cancel", "Skip (Faster)")); onRenderingBatch = onRenderingBatch == 1 ? 0 : (onRenderingBatch == 0 ? 1 : 2); if (onRenderingBatch > 0) { DoBatchRendering(); } } EditorGUI.BeginDisabledGroup(onRendering); GUI.backgroundColor = new Color(0.5f, 0, 0.5f); if (GUILayout.Button("Delete All SDF Asset")) { if (EditorUtility.DisplayDialog("Confirm Deletion", "Are you sure you want to delete ALL SDF Font Asset?", "Yes", "No")) { var fonts = TEXPreference.main.fonts; for (int i = 0; i < fonts.Length; i++) { EditorUtility.DisplayProgressBar("Please wait", "Reimporting Fonts...", i / (float)fonts.Length); if (fonts[i].type == TexAssetType.FontSigned) { AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(((TexFontSigned)fonts[i]).asset)); Deconvert((TexFontSigned)fonts[i]); } } TEXPreference.main.RebuildMaterial(); EditorUtility.ClearProgressBar(); } } GUI.backgroundColor = Color.white; EditorGUI.EndDisabledGroup(); } EditorGUI.EndDisabledGroup(); if (onRendering) { var prog = TMPro_FontPlugin.Check_RenderProgress(); EditorGUI.ProgressBar(EditorGUILayout.GetControlRect(), prog, prog.ToString("P")); if (onRenderingBatch > 0) { if (onRenderingBatch == 3) { EditorGUILayout.HelpBox("Will be stopped after current rendering is done", MessageType.Info); } else { GUI.backgroundColor = Color.yellow; if (GUILayout.Button("Cancel")) { onRenderingBatch = 3; } GUI.backgroundColor = Color.white; } } } }
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; if (onRendering) { //CheckErr(TMPro_FontPlugin.Destroy_FontEngine()); 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 { if (onRendering) { //CheckErr(TMPro_FontPlugin.Destroy_FontEngine()); 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) { 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(); } }; }); }
static void RenderUpdate() { if (renderCompleted) { if (textureChannel == 0) { for (int i = 0; i < textureColors.Length; i++) { textureColors[i].r = textureBuffer[i]; } } if (textureChannel == 1) { for (int i = 0; i < textureColors.Length; i++) { textureColors[i].g = textureBuffer[i]; } } if (textureChannel == 2) { for (int i = 0; i < textureColors.Length; i++) { textureColors[i].b = textureBuffer[i]; } } if (textureChannel == 3) { for (int i = 0; i < textureColors.Length; i++) { textureColors[i].a = textureBuffer[i]; } } var size = (float)textureSize; var ascender = faceInfo.ascender; var glyphCount = faceInfo.characterCount; var charSet = new HashSet <int>(); for (int i = 0; i < glyphCount; i++) { var charInfo = new CharacterInfo(); var id = glyphInfo[i].id; var x = (glyphInfo[i].x - charPadding); var y = (glyphInfo[i].y - charPadding); var width = (glyphInfo[i].width + charPadding + charPadding); var height = (glyphInfo[i].height + charPadding + charPadding); var xOffset = glyphInfo[i].xOffset; var yOffset = glyphInfo[i].yOffset - ascender; var xAdvance = glyphInfo[i].xAdvance; var uvMinX = Mathf.Round(x) / size; var uvMinY = Mathf.Round(size - y - height) / size; var uvMaxX = Mathf.Round(x + width) / size; var uvMaxY = Mathf.Round(size - y) / size; charInfoList.Add(charInfo); charInfo.uvTopLeft = new Vector2(uvMinX, uvMinY); charInfo.uvTopRight = new Vector2(uvMaxX, uvMinY); charInfo.uvBottomLeft = new Vector2(uvMinX, uvMaxY); charInfo.uvBottomRight = new Vector2(uvMaxX, uvMaxY); charInfo.minX = Mathf.RoundToInt(xOffset); charInfo.minY = Mathf.RoundToInt(yOffset); charInfo.maxX = Mathf.RoundToInt(xOffset + width); charInfo.maxY = Mathf.RoundToInt(yOffset - height); charInfo.advance = Mathf.RoundToInt(xAdvance); charInfo.index = id; charSet.Add(id); } for (int i = 0; i < charCodes.Length; i++) { if (!charSet.Contains(charCodes[i])) { Debug.Log("Missing: " + (char)charCodes[i] + "|" + i + "|" + charCodes[i] + "|0x" + charCodes[i].ToString("X4")); } } Debug.Log("Glyph:" + glyphCount + ", " + charCodes[0] + " - " + charCodes[charCodes.Length - 1]); if (textureChannel < 3) { CreateTexture(textureChannel + 1); } else { EditorUtility.ClearProgressBar(); EditorApplication.update -= RenderUpdate; TMPro_FontPlugin.Destroy_FontEngine(); var texturePath = outputFolder + fontName + ".png"; var materialPath = outputFolder + fontName + ".mat"; var fontPath = outputFolder + fontName + ".fontsettings"; var texture = new Texture2D(textureSize, textureSize, TextureFormat.RGBA32, false, true); texture.SetPixels32(textureColors); File.WriteAllBytes(texturePath, texture.EncodeToPNG()); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); var import = AssetImporter.GetAtPath(texturePath) as TextureImporter; import.textureCompression = TextureImporterCompression.Uncompressed; import.alphaIsTransparency = false; import.mipmapEnabled = false; AssetDatabase.ImportAsset(texturePath); var material = new Material(Shader.Find("SDF/GBK/Text")); material.mainTexture = AssetDatabase.LoadAssetAtPath <Texture2D>(texturePath); AssetDatabase.CreateAsset(material, materialPath); var font = new Font(fontName); var mFont = new SerializedObject(font); mFont.FindProperty("m_FontSize").floatValue = faceInfo.pointSize; mFont.FindProperty("m_LineSpacing").floatValue = faceInfo.lineHeight; mFont.ApplyModifiedProperties(); font.material = material; font.characterInfo = charInfoList.ToArray(); AssetDatabase.CreateAsset(font, fontPath); } } else { float progress = TMPro_FontPlugin.Check_RenderProgress(); string progressText = "Channel: " + textureChannel + " , Char: " + (int)(progress * charCount) + "/" + charCount; EditorUtility.DisplayProgressBar("Create Font", progressText, progress); } }
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); }
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; }); } } }
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); }); }