| using System; |
| using UnityEngine; |
| using UnityEngine.Serialization; |
| using UnityEngine.TextCore; |
| using UnityEngine.TextCore.LowLevel; |
| using Unity.Profiling; |
| using System.Collections.Generic; |
| using System.Linq; |
|
|
| #if UNITY_EDITOR && UNITY_2018_4_OR_NEWER && !UNITY_2018_4_0 && !UNITY_2018_4_1 && !UNITY_2018_4_2 && !UNITY_2018_4_3 && !UNITY_2018_4_4 |
| using UnityEditor.TextCore.LowLevel; |
| #endif |
|
|
|
|
| namespace TMPro |
| { |
| public enum AtlasPopulationMode |
| { |
| Static = 0x0, |
| Dynamic = 0x1, |
| } |
|
|
|
|
| [Serializable][ExcludeFromPresetAttribute] |
| public class TMP_FontAsset : TMP_Asset |
| { |
| |
| |
| |
| |
| public string version |
| { |
| get { return m_Version; } |
| internal set { m_Version = value; } |
| } |
| [SerializeField] |
| private string m_Version; |
|
|
| |
| |
| |
| [SerializeField] |
| internal string m_SourceFontFileGUID; |
|
|
| #if UNITY_EDITOR |
| |
| |
| |
| [SerializeField] |
| internal Font m_SourceFontFile_EditorRef; |
| #endif |
|
|
| |
| |
| |
| public Font sourceFontFile |
| { |
| get { return m_SourceFontFile; } |
| internal set { m_SourceFontFile = value; } |
| } |
| [SerializeField] |
| private Font m_SourceFontFile; |
|
|
| public AtlasPopulationMode atlasPopulationMode |
| { |
| get { return m_AtlasPopulationMode; } |
|
|
| set |
| { |
| m_AtlasPopulationMode = value; |
|
|
| #if UNITY_EDITOR |
| if (m_AtlasPopulationMode == AtlasPopulationMode.Static) |
| m_SourceFontFile = null; |
| else if (m_AtlasPopulationMode == AtlasPopulationMode.Dynamic) |
| m_SourceFontFile = m_SourceFontFile_EditorRef; |
| #endif |
| } |
| } |
| [SerializeField] |
| private AtlasPopulationMode m_AtlasPopulationMode; |
|
|
|
|
| |
| |
| |
| public FaceInfo faceInfo |
| { |
| get { return m_FaceInfo; } |
| set { m_FaceInfo = value; } |
| } |
| [SerializeField] |
| internal FaceInfo m_FaceInfo; |
|
|
|
|
| |
| |
| |
| public List<Glyph> glyphTable |
| { |
| get { return m_GlyphTable; } |
| internal set { m_GlyphTable = value; } |
| } |
| [SerializeField] |
| internal List<Glyph> m_GlyphTable = new List<Glyph>(); |
|
|
| |
| |
| |
| public Dictionary<uint, Glyph> glyphLookupTable |
| { |
| get |
| { |
| if (m_GlyphLookupDictionary == null) |
| ReadFontAssetDefinition(); |
|
|
| return m_GlyphLookupDictionary; |
| } |
| } |
| internal Dictionary<uint, Glyph> m_GlyphLookupDictionary; |
|
|
|
|
| |
| |
| |
| public List<TMP_Character> characterTable |
| { |
| get { return m_CharacterTable; } |
| internal set { m_CharacterTable = value; } |
| } |
| [SerializeField] |
| internal List<TMP_Character> m_CharacterTable = new List<TMP_Character>(); |
|
|
| |
| |
| |
| public Dictionary<uint, TMP_Character> characterLookupTable |
| { |
| get |
| { |
| if (m_CharacterLookupDictionary == null) |
| ReadFontAssetDefinition(); |
|
|
|
|
| return m_CharacterLookupDictionary; |
| } |
| } |
| internal Dictionary<uint, TMP_Character> m_CharacterLookupDictionary; |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| public Texture2D atlasTexture |
| { |
| get |
| { |
| if (m_AtlasTexture == null) |
| { |
| m_AtlasTexture = atlasTextures[0]; |
| } |
|
|
| return m_AtlasTexture; |
| } |
| } |
| internal Texture2D m_AtlasTexture; |
|
|
| |
| |
| |
| public Texture2D[] atlasTextures |
| { |
| get |
| { |
| if (m_AtlasTextures == null) |
| { |
| |
| } |
|
|
| |
| |
|
|
| return m_AtlasTextures; |
| } |
|
|
| set |
| { |
| m_AtlasTextures = value; |
| } |
| } |
| [SerializeField] |
| internal Texture2D[] m_AtlasTextures; |
|
|
| |
| |
| |
| [SerializeField] |
| internal int m_AtlasTextureIndex; |
|
|
| |
| |
| |
| public int atlasTextureCount { get { return m_AtlasTextureIndex + 1; } } |
|
|
| |
| |
| |
| public bool isMultiAtlasTexturesEnabled |
| { |
| get { return m_IsMultiAtlasTexturesEnabled; } |
| set { m_IsMultiAtlasTexturesEnabled = value; } |
| } |
|
|
| [SerializeField] |
| private bool m_IsMultiAtlasTexturesEnabled; |
|
|
| |
| |
| |
| internal bool clearDynamicDataOnBuild |
| { |
| get { return m_ClearDynamicDataOnBuild; } |
| set { m_ClearDynamicDataOnBuild = value; } |
| } |
| [SerializeField] |
| private bool m_ClearDynamicDataOnBuild; |
|
|
| |
| |
| |
| internal List<GlyphRect> usedGlyphRects |
| { |
| get { return m_UsedGlyphRects; } |
| set { m_UsedGlyphRects = value; } |
| } |
| [SerializeField] |
| private List<GlyphRect> m_UsedGlyphRects; |
|
|
| |
| |
| |
| internal List<GlyphRect> freeGlyphRects |
| { |
| get { return m_FreeGlyphRects; } |
| set { m_FreeGlyphRects = value; } |
| } |
| [SerializeField] |
| private List<GlyphRect> m_FreeGlyphRects; |
|
|
| |
| |
| |
| |
| [Obsolete("The fontInfo property and underlying type is now obsolete. Please use the faceInfo property and FaceInfo type instead.")] |
| public FaceInfo_Legacy fontInfo |
| { |
| get { return m_fontInfo; } |
| } |
|
|
| [SerializeField] |
| private FaceInfo_Legacy m_fontInfo = null; |
|
|
| |
| |
| |
| [SerializeField] |
| public Texture2D atlas; |
|
|
| |
| |
| |
| public int atlasWidth |
| { |
| get { return m_AtlasWidth; } |
| internal set { m_AtlasWidth = value; } |
| } |
| [SerializeField] |
| internal int m_AtlasWidth; |
|
|
| |
| |
| |
| public int atlasHeight |
| { |
| get { return m_AtlasHeight; } |
| internal set { m_AtlasHeight = value; } |
| } |
| [SerializeField] |
| internal int m_AtlasHeight; |
|
|
| |
| |
| |
| public int atlasPadding |
| { |
| get { return m_AtlasPadding; } |
| internal set { m_AtlasPadding = value; } |
| } |
| [SerializeField] |
| internal int m_AtlasPadding; |
|
|
| public GlyphRenderMode atlasRenderMode |
| { |
| get { return m_AtlasRenderMode; } |
| internal set { m_AtlasRenderMode = value; } |
| } |
| [SerializeField] |
| internal GlyphRenderMode m_AtlasRenderMode; |
|
|
| |
| [SerializeField] |
| internal List<TMP_Glyph> m_glyphInfoList; |
|
|
| [SerializeField] |
| [FormerlySerializedAs("m_kerningInfo")] |
| internal KerningTable m_KerningTable = new KerningTable(); |
|
|
| |
| |
| |
| public TMP_FontFeatureTable fontFeatureTable |
| { |
| get { return m_FontFeatureTable; } |
| internal set { m_FontFeatureTable = value; } |
| } |
| [SerializeField] |
| internal TMP_FontFeatureTable m_FontFeatureTable = new TMP_FontFeatureTable(); |
|
|
| |
| [SerializeField] |
| #pragma warning disable 0649 |
| private List<TMP_FontAsset> fallbackFontAssets; |
|
|
| |
| |
| |
| public List<TMP_FontAsset> fallbackFontAssetTable |
| { |
| get { return m_FallbackFontAssetTable; } |
| set { m_FallbackFontAssetTable = value; } |
| } |
| [SerializeField] |
| internal List<TMP_FontAsset> m_FallbackFontAssetTable; |
|
|
| |
| |
| |
| public FontAssetCreationSettings creationSettings |
| { |
| get { return m_CreationSettings; } |
| set { m_CreationSettings = value; } |
| } |
| [SerializeField] |
| internal FontAssetCreationSettings m_CreationSettings; |
|
|
| |
| |
| |
| public TMP_FontWeightPair[] fontWeightTable |
| { |
| get { return m_FontWeightTable; } |
| internal set { m_FontWeightTable = value; } |
| } |
| [SerializeField] |
| private TMP_FontWeightPair[] m_FontWeightTable = new TMP_FontWeightPair[10]; |
|
|
| |
| |
| |
| |
| |
| [SerializeField] |
| private TMP_FontWeightPair[] fontWeights = null; |
|
|
| |
|
|
| |
| |
| |
| public float normalStyle = 0; |
|
|
| |
| |
| |
| public float normalSpacingOffset = 0; |
|
|
| |
| |
| |
| public float boldStyle = 0.75f; |
|
|
| |
| |
| |
| public float boldSpacing = 7f; |
|
|
| |
| |
| |
| public byte italicStyle = 35; |
|
|
| public byte tabSize = 10; |
|
|
| internal bool IsFontAssetLookupTablesDirty; |
|
|
| |
| private static ProfilerMarker k_ReadFontAssetDefinitionMarker = new ProfilerMarker("TMP.ReadFontAssetDefinition"); |
| private static ProfilerMarker k_AddSynthesizedCharactersMarker = new ProfilerMarker("TMP.AddSynthesizedCharacters"); |
| private static ProfilerMarker k_TryAddCharacterMarker = new ProfilerMarker("TMP.TryAddCharacter"); |
| private static ProfilerMarker k_TryAddCharactersMarker = new ProfilerMarker("TMP.TryAddCharacters"); |
| private static ProfilerMarker k_UpdateGlyphAdjustmentRecordsMarker = new ProfilerMarker("TMP.UpdateGlyphAdjustmentRecords"); |
| private static ProfilerMarker k_ClearFontAssetDataMarker = new ProfilerMarker("TMP.ClearFontAssetData"); |
| private static ProfilerMarker k_UpdateFontAssetDataMarker = new ProfilerMarker("TMP.UpdateFontAssetData"); |
|
|
| |
| |
| |
| |
| |
| public static TMP_FontAsset CreateFontAsset(Font font) |
| { |
| return CreateFontAsset(font, 90, 9, GlyphRenderMode.SDFAA, 1024, 1024, AtlasPopulationMode.Dynamic); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public static TMP_FontAsset CreateFontAsset(Font font, int samplingPointSize, int atlasPadding, GlyphRenderMode renderMode, int atlasWidth, int atlasHeight, AtlasPopulationMode atlasPopulationMode = AtlasPopulationMode.Dynamic, bool enableMultiAtlasSupport = true) |
| { |
| |
| FontEngine.InitializeFontEngine(); |
|
|
| |
| if (FontEngine.LoadFontFace(font, samplingPointSize) != FontEngineError.Success) |
| { |
| Debug.LogWarning("Unable to load font face for [" + font.name + "]. Make sure \"Include Font Data\" is enabled in the Font Import Settings.", font); |
| return null; |
| } |
|
|
| |
| TMP_FontAsset fontAsset = ScriptableObject.CreateInstance<TMP_FontAsset>(); |
|
|
| fontAsset.m_Version = "1.1.0"; |
| fontAsset.faceInfo = FontEngine.GetFaceInfo(); |
|
|
| |
| if (atlasPopulationMode == AtlasPopulationMode.Dynamic) |
| fontAsset.sourceFontFile = font; |
|
|
| |
| #if UNITY_EDITOR |
| string guid; |
| long localID; |
|
|
| UnityEditor.AssetDatabase.TryGetGUIDAndLocalFileIdentifier(font, out guid, out localID); |
| fontAsset.m_SourceFontFileGUID = guid; |
| fontAsset.m_SourceFontFile_EditorRef = font; |
| #endif |
|
|
| fontAsset.atlasPopulationMode = atlasPopulationMode; |
|
|
| fontAsset.atlasWidth = atlasWidth; |
| fontAsset.atlasHeight = atlasHeight; |
| fontAsset.atlasPadding = atlasPadding; |
| fontAsset.atlasRenderMode = renderMode; |
|
|
| |
| fontAsset.atlasTextures = new Texture2D[1]; |
|
|
| |
| Texture2D texture = new Texture2D(0, 0, TextureFormat.Alpha8, false); |
| fontAsset.atlasTextures[0] = texture; |
|
|
| fontAsset.isMultiAtlasTexturesEnabled = enableMultiAtlasSupport; |
|
|
| |
| int packingModifier; |
| if (((GlyphRasterModes)renderMode & GlyphRasterModes.RASTER_MODE_BITMAP) == GlyphRasterModes.RASTER_MODE_BITMAP) |
| { |
| packingModifier = 0; |
|
|
| |
| Material tmp_material = new Material(ShaderUtilities.ShaderRef_MobileBitmap); |
|
|
| |
| tmp_material.SetTexture(ShaderUtilities.ID_MainTex, texture); |
| tmp_material.SetFloat(ShaderUtilities.ID_TextureWidth, atlasWidth); |
| tmp_material.SetFloat(ShaderUtilities.ID_TextureHeight, atlasHeight); |
|
|
| fontAsset.material = tmp_material; |
| } |
| else |
| { |
| packingModifier = 1; |
|
|
| |
| Material tmp_material = new Material(ShaderUtilities.ShaderRef_MobileSDF); |
|
|
| |
| tmp_material.SetTexture(ShaderUtilities.ID_MainTex, texture); |
| tmp_material.SetFloat(ShaderUtilities.ID_TextureWidth, atlasWidth); |
| tmp_material.SetFloat(ShaderUtilities.ID_TextureHeight, atlasHeight); |
|
|
| tmp_material.SetFloat(ShaderUtilities.ID_GradientScale, atlasPadding + packingModifier); |
|
|
| tmp_material.SetFloat(ShaderUtilities.ID_WeightNormal, fontAsset.normalStyle); |
| tmp_material.SetFloat(ShaderUtilities.ID_WeightBold, fontAsset.boldStyle); |
|
|
| fontAsset.material = tmp_material; |
| } |
|
|
| fontAsset.freeGlyphRects = new List<GlyphRect>(8) { new GlyphRect(0, 0, atlasWidth - packingModifier, atlasHeight - packingModifier) }; |
| fontAsset.usedGlyphRects = new List<GlyphRect>(8); |
|
|
| |
|
|
| fontAsset.ReadFontAssetDefinition(); |
|
|
| return fontAsset; |
| } |
|
|
|
|
| void Awake() |
| { |
| |
| if (this.material != null && string.IsNullOrEmpty(m_Version)) |
| UpgradeFontAsset(); |
| } |
|
|
| #if UNITY_EDITOR |
| private void OnValidate() |
| { |
| |
| if (m_CharacterLookupDictionary == null || m_GlyphLookupDictionary == null) |
| ReadFontAssetDefinition(); |
| } |
| #endif |
|
|
| private static string s_DefaultMaterialSuffix = " Atlas Material"; |
|
|
| public void ReadFontAssetDefinition() |
| { |
| k_ReadFontAssetDefinitionMarker.Begin(); |
|
|
| |
|
|
| |
| if (this.material != null && string.IsNullOrEmpty(m_Version)) |
| UpgradeFontAsset(); |
|
|
| |
| InitializeDictionaryLookupTables(); |
|
|
| |
| AddSynthesizedCharactersAndFaceMetrics(); |
|
|
| |
| if (m_FaceInfo.scale == 0) |
| m_FaceInfo.scale = 1.0f; |
|
|
| |
| if (m_FaceInfo.strikethroughOffset == 0) |
| m_FaceInfo.strikethroughOffset = m_FaceInfo.capLine / 2.5f; |
|
|
| |
| if (m_AtlasPadding == 0) |
| { |
| if (material.HasProperty(ShaderUtilities.ID_GradientScale)) |
| m_AtlasPadding = (int)material.GetFloat(ShaderUtilities.ID_GradientScale) - 1; |
| } |
|
|
| |
| hashCode = TMP_TextUtilities.GetSimpleHashCode(this.name); |
|
|
| |
| materialHashCode = TMP_TextUtilities.GetSimpleHashCode(this.name + s_DefaultMaterialSuffix); |
|
|
| |
| |
|
|
| IsFontAssetLookupTablesDirty = false; |
|
|
| k_ReadFontAssetDefinitionMarker.End(); |
| } |
|
|
|
|
| |
| |
| |
| internal void InitializeDictionaryLookupTables() |
| { |
| |
| InitializeGlyphLookupDictionary(); |
|
|
| |
| InitializeCharacterLookupDictionary(); |
|
|
| |
| InitializeGlyphPaidAdjustmentRecordsLookupDictionary(); |
| } |
|
|
| internal void InitializeGlyphLookupDictionary() |
| { |
| |
| if (m_GlyphLookupDictionary == null) |
| m_GlyphLookupDictionary = new Dictionary<uint, Glyph>(); |
| else |
| m_GlyphLookupDictionary.Clear(); |
|
|
| |
| if (m_GlyphIndexList == null) |
| m_GlyphIndexList = new List<uint>(); |
| else |
| m_GlyphIndexList.Clear(); |
|
|
| |
| if (m_GlyphIndexListNewlyAdded == null) |
| m_GlyphIndexListNewlyAdded = new List<uint>(); |
| else |
| m_GlyphIndexListNewlyAdded.Clear(); |
|
|
| |
| int glyphCount = m_GlyphTable.Count; |
|
|
| |
| for (int i = 0; i < glyphCount; i++) |
| { |
| Glyph glyph = m_GlyphTable[i]; |
|
|
| uint index = glyph.index; |
|
|
| |
| if (m_GlyphLookupDictionary.ContainsKey(index) == false) |
| { |
| m_GlyphLookupDictionary.Add(index, glyph); |
| m_GlyphIndexList.Add(index); |
| } |
| } |
| } |
|
|
| internal void InitializeCharacterLookupDictionary() |
| { |
| |
| if (m_CharacterLookupDictionary == null) |
| m_CharacterLookupDictionary = new Dictionary<uint, TMP_Character>(); |
| else |
| m_CharacterLookupDictionary.Clear(); |
|
|
| |
| for (int i = 0; i < m_CharacterTable.Count; i++) |
| { |
| TMP_Character character = m_CharacterTable[i]; |
|
|
| uint unicode = character.unicode; |
| uint glyphIndex = character.glyphIndex; |
|
|
| |
| if (m_CharacterLookupDictionary.ContainsKey(unicode) == false) |
| { |
| m_CharacterLookupDictionary.Add(unicode, character); |
| character.textAsset = this; |
| character.glyph = m_GlyphLookupDictionary[glyphIndex]; |
| } |
| } |
|
|
| |
| if (FallbackSearchQueryLookup == null) |
| FallbackSearchQueryLookup = new HashSet<int>(); |
| else |
| FallbackSearchQueryLookup.Clear(); |
| } |
|
|
| internal void InitializeGlyphPaidAdjustmentRecordsLookupDictionary() |
| { |
| |
| if (m_KerningTable != null && m_KerningTable.kerningPairs != null && m_KerningTable.kerningPairs.Count > 0) |
| UpgradeGlyphAdjustmentTableToFontFeatureTable(); |
|
|
| |
| if (m_FontFeatureTable.m_GlyphPairAdjustmentRecordLookupDictionary == null) |
| m_FontFeatureTable.m_GlyphPairAdjustmentRecordLookupDictionary = new Dictionary<uint, TMP_GlyphPairAdjustmentRecord>(); |
| else |
| m_FontFeatureTable.m_GlyphPairAdjustmentRecordLookupDictionary.Clear(); |
|
|
| List<TMP_GlyphPairAdjustmentRecord> glyphPairAdjustmentRecords = m_FontFeatureTable.m_GlyphPairAdjustmentRecords; |
| if (glyphPairAdjustmentRecords != null) |
| { |
| for (int i = 0; i < glyphPairAdjustmentRecords.Count; i++) |
| { |
| TMP_GlyphPairAdjustmentRecord record = glyphPairAdjustmentRecords[i]; |
|
|
| uint key = new GlyphPairKey(record).key; |
|
|
| if (!m_FontFeatureTable.m_GlyphPairAdjustmentRecordLookupDictionary.ContainsKey(key)) |
| m_FontFeatureTable.m_GlyphPairAdjustmentRecordLookupDictionary.Add(key, record); |
| } |
| } |
| } |
|
|
| internal void AddSynthesizedCharactersAndFaceMetrics() |
| { |
| k_AddSynthesizedCharactersMarker.Begin(); |
|
|
| bool isFontFaceLoaded = false; |
|
|
| if (m_AtlasPopulationMode == AtlasPopulationMode.Dynamic) |
| isFontFaceLoaded = FontEngine.LoadFontFace(sourceFontFile, m_FaceInfo.pointSize) == FontEngineError.Success; |
|
|
| |
|
|
| |
| |
| AddSynthesizedCharacter(0x03, isFontFaceLoaded, true); |
|
|
| |
| AddSynthesizedCharacter(0x09, isFontFaceLoaded, true); |
|
|
| |
| AddSynthesizedCharacter(0x0A, isFontFaceLoaded); |
|
|
| |
| AddSynthesizedCharacter(0x0B, isFontFaceLoaded); |
|
|
| |
| AddSynthesizedCharacter(0x0D, isFontFaceLoaded); |
|
|
| |
| AddSynthesizedCharacter(0x061C, isFontFaceLoaded); |
|
|
| |
| AddSynthesizedCharacter(0x200B, isFontFaceLoaded); |
|
|
| |
| AddSynthesizedCharacter(0x200E, isFontFaceLoaded); |
|
|
| |
| AddSynthesizedCharacter(0x200F, isFontFaceLoaded); |
|
|
| |
| AddSynthesizedCharacter(0x2028, isFontFaceLoaded); |
|
|
| |
| AddSynthesizedCharacter(0x2029, isFontFaceLoaded); |
|
|
| |
| AddSynthesizedCharacter(0x2060, isFontFaceLoaded); |
|
|
| |
| if (m_FaceInfo.capLine == 0 && m_CharacterLookupDictionary.ContainsKey('X')) |
| { |
| uint glyphIndex = m_CharacterLookupDictionary['X'].glyphIndex; |
| m_FaceInfo.capLine = m_GlyphLookupDictionary[glyphIndex].metrics.horizontalBearingY; |
| } |
|
|
| |
| if (m_FaceInfo.meanLine == 0 && m_CharacterLookupDictionary.ContainsKey('x')) |
| { |
| uint glyphIndex = m_CharacterLookupDictionary['x'].glyphIndex; |
| m_FaceInfo.meanLine = m_GlyphLookupDictionary[glyphIndex].metrics.horizontalBearingY; |
| } |
|
|
| k_AddSynthesizedCharactersMarker.End(); |
| } |
|
|
| void AddSynthesizedCharacter(uint unicode, bool isFontFaceLoaded, bool addImmediately = false) |
| { |
| |
| if (m_CharacterLookupDictionary.ContainsKey(unicode)) |
| return; |
|
|
| Glyph glyph; |
|
|
| if (isFontFaceLoaded) |
| { |
| |
| if (FontEngine.GetGlyphIndex(unicode) != 0) |
| { |
| if (addImmediately == false) |
| return; |
|
|
| |
|
|
| GlyphLoadFlags glyphLoadFlags = ((GlyphRasterModes)m_AtlasRenderMode & GlyphRasterModes.RASTER_MODE_NO_HINTING) == GlyphRasterModes.RASTER_MODE_NO_HINTING |
| ? GlyphLoadFlags.LOAD_NO_BITMAP | GlyphLoadFlags.LOAD_NO_HINTING |
| : GlyphLoadFlags.LOAD_NO_BITMAP; |
|
|
| if (FontEngine.TryGetGlyphWithUnicodeValue(unicode, glyphLoadFlags, out glyph)) |
| m_CharacterLookupDictionary.Add(unicode, new TMP_Character(unicode, this, glyph)); |
|
|
| return; |
| } |
| } |
|
|
| |
|
|
| |
| glyph = new Glyph(0, new GlyphMetrics(0, 0, 0, 0, 0), GlyphRect.zero, 1.0f, 0); |
| m_CharacterLookupDictionary.Add(unicode, new TMP_Character(unicode, this, glyph)); |
| } |
|
|
| internal HashSet<int> FallbackSearchQueryLookup = new HashSet<int>(); |
|
|
| internal void AddCharacterToLookupCache(uint unicode, TMP_Character character) |
| { |
| m_CharacterLookupDictionary.Add(unicode, character); |
|
|
| |
| FallbackSearchQueryLookup.Add(character.textAsset.instanceID); |
| } |
|
|
| |
| |
| |
| internal void SortCharacterTable() |
| { |
| if (m_CharacterTable != null && m_CharacterTable.Count > 0) |
| m_CharacterTable = m_CharacterTable.OrderBy(c => c.unicode).ToList(); |
| } |
|
|
| |
| |
| |
| internal void SortGlyphTable() |
| { |
| if (m_GlyphTable != null && m_GlyphTable.Count > 0) |
| m_GlyphTable = m_GlyphTable.OrderBy(c => c.index).ToList(); |
| } |
|
|
| internal void SortFontFeatureTable() |
| { |
| m_FontFeatureTable.SortGlyphPairAdjustmentRecords(); |
| } |
|
|
| |
| |
| |
| internal void SortAllTables() |
| { |
| SortGlyphTable(); |
| SortCharacterTable(); |
| SortFontFeatureTable(); |
| } |
|
|
| |
| |
| |
| private static HashSet<int> k_SearchedFontAssetLookup; |
|
|
| |
| |
| |
| |
| |
| public bool HasCharacter(int character) |
| { |
| if (m_CharacterLookupDictionary == null) |
| return false; |
|
|
| return m_CharacterLookupDictionary.ContainsKey((uint)character); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| public bool HasCharacter(char character, bool searchFallbacks = false, bool tryAddCharacter = false) |
| { |
| |
| if (m_CharacterLookupDictionary == null) |
| { |
| ReadFontAssetDefinition(); |
|
|
| if (m_CharacterLookupDictionary == null) |
| return false; |
| } |
|
|
| |
| if (m_CharacterLookupDictionary.ContainsKey(character)) |
| return true; |
|
|
| |
| if (tryAddCharacter && m_AtlasPopulationMode == AtlasPopulationMode.Dynamic) |
| { |
| TMP_Character returnedCharacter; |
|
|
| if (TryAddCharacterInternal(character, out returnedCharacter)) |
| return true; |
| } |
|
|
| if (searchFallbacks) |
| { |
| |
| if (k_SearchedFontAssetLookup == null) |
| k_SearchedFontAssetLookup = new HashSet<int>(); |
| else |
| k_SearchedFontAssetLookup.Clear(); |
|
|
| |
| k_SearchedFontAssetLookup.Add(GetInstanceID()); |
|
|
| |
| if (fallbackFontAssetTable != null && fallbackFontAssetTable.Count > 0) |
| { |
| for (int i = 0; i < fallbackFontAssetTable.Count && fallbackFontAssetTable[i] != null; i++) |
| { |
| TMP_FontAsset fallback = fallbackFontAssetTable[i]; |
| int fallbackID = fallback.GetInstanceID(); |
|
|
| |
| if (k_SearchedFontAssetLookup.Add(fallbackID)) |
| { |
| if (fallback.HasCharacter_Internal(character, true, tryAddCharacter)) |
| return true; |
| } |
| } |
| } |
|
|
| |
| if (TMP_Settings.fallbackFontAssets != null && TMP_Settings.fallbackFontAssets.Count > 0) |
| { |
| for (int i = 0; i < TMP_Settings.fallbackFontAssets.Count && TMP_Settings.fallbackFontAssets[i] != null; i++) |
| { |
| TMP_FontAsset fallback = TMP_Settings.fallbackFontAssets[i]; |
| int fallbackID = fallback.GetInstanceID(); |
|
|
| |
| if (k_SearchedFontAssetLookup.Add(fallbackID)) |
| { |
| if (fallback.HasCharacter_Internal(character, true, tryAddCharacter)) |
| return true; |
| } |
| } |
| } |
|
|
| |
| if (TMP_Settings.defaultFontAsset != null) |
| { |
| TMP_FontAsset fallback = TMP_Settings.defaultFontAsset; |
| int fallbackID = fallback.GetInstanceID(); |
|
|
| |
| if (k_SearchedFontAssetLookup.Add(fallbackID)) |
| { |
| if (fallback.HasCharacter_Internal(character, true, tryAddCharacter)) |
| return true; |
| } |
| } |
| } |
|
|
| return false; |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| bool HasCharacter_Internal(uint character, bool searchFallbacks = false, bool tryAddCharacter = false) |
| { |
| |
| if (m_CharacterLookupDictionary == null) |
| { |
| ReadFontAssetDefinition(); |
|
|
| if (m_CharacterLookupDictionary == null) |
| return false; |
| } |
|
|
| |
| if (m_CharacterLookupDictionary.ContainsKey(character)) |
| return true; |
|
|
| |
| if (tryAddCharacter && atlasPopulationMode == AtlasPopulationMode.Dynamic) |
| { |
| TMP_Character returnedCharacter; |
|
|
| if (TryAddCharacterInternal(character, out returnedCharacter)) |
| return true; |
| } |
|
|
| if (searchFallbacks) |
| { |
| |
| if (fallbackFontAssetTable == null || fallbackFontAssetTable.Count == 0) |
| return false; |
|
|
| for (int i = 0; i < fallbackFontAssetTable.Count && fallbackFontAssetTable[i] != null; i++) |
| { |
| TMP_FontAsset fallback = fallbackFontAssetTable[i]; |
| int fallbackID = fallback.GetInstanceID(); |
|
|
| |
| if (k_SearchedFontAssetLookup.Add(fallbackID)) |
| { |
| if (fallback.HasCharacter_Internal(character, true, tryAddCharacter)) |
| return true; |
| } |
| } |
| } |
|
|
| return false; |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| |
| public bool HasCharacters(string text, out List<char> missingCharacters) |
| { |
| if (m_CharacterLookupDictionary == null) |
| { |
| missingCharacters = null; |
| return false; |
| } |
|
|
| missingCharacters = new List<char>(); |
|
|
| for (int i = 0; i < text.Length; i++) |
| { |
| if (!m_CharacterLookupDictionary.ContainsKey(text[i])) |
| missingCharacters.Add(text[i]); |
| } |
|
|
| if (missingCharacters.Count == 0) |
| return true; |
|
|
| return false; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| public bool HasCharacters(string text, out uint[] missingCharacters, bool searchFallbacks = false, bool tryAddCharacter = false) |
| { |
| missingCharacters = null; |
|
|
| |
| if (m_CharacterLookupDictionary == null) |
| { |
| ReadFontAssetDefinition(); |
|
|
| if (m_CharacterLookupDictionary == null) |
| return false; |
| } |
|
|
| |
| s_MissingCharacterList.Clear(); |
|
|
| for (int i = 0; i < text.Length; i++) |
| { |
| bool isMissingCharacter = true; |
| uint character = text[i]; |
|
|
| if (m_CharacterLookupDictionary.ContainsKey(character)) |
| continue; |
|
|
| |
| if (tryAddCharacter && atlasPopulationMode == AtlasPopulationMode.Dynamic) |
| { |
| TMP_Character returnedCharacter; |
|
|
| if (TryAddCharacterInternal(character, out returnedCharacter)) |
| continue; |
| } |
|
|
| if (searchFallbacks) |
| { |
| |
| if (k_SearchedFontAssetLookup == null) |
| k_SearchedFontAssetLookup = new HashSet<int>(); |
| else |
| k_SearchedFontAssetLookup.Clear(); |
|
|
| |
| k_SearchedFontAssetLookup.Add(GetInstanceID()); |
|
|
| |
| if (fallbackFontAssetTable != null && fallbackFontAssetTable.Count > 0) |
| { |
| for (int j = 0; j < fallbackFontAssetTable.Count && fallbackFontAssetTable[j] != null; j++) |
| { |
| TMP_FontAsset fallback = fallbackFontAssetTable[j]; |
| int fallbackID = fallback.GetInstanceID(); |
|
|
| |
| if (k_SearchedFontAssetLookup.Add(fallbackID)) |
| { |
| if (fallback.HasCharacter_Internal(character, true, tryAddCharacter) == false) |
| continue; |
|
|
| isMissingCharacter = false; |
| break; |
| } |
| } |
| } |
|
|
| |
| if (isMissingCharacter && TMP_Settings.fallbackFontAssets != null && TMP_Settings.fallbackFontAssets.Count > 0) |
| { |
| for (int j = 0; j < TMP_Settings.fallbackFontAssets.Count && TMP_Settings.fallbackFontAssets[j] != null; j++) |
| { |
| TMP_FontAsset fallback = TMP_Settings.fallbackFontAssets[j]; |
| int fallbackID = fallback.GetInstanceID(); |
|
|
| |
| if (k_SearchedFontAssetLookup.Add(fallbackID)) |
| { |
| if (fallback.HasCharacter_Internal(character, true, tryAddCharacter) == false) |
| continue; |
|
|
| isMissingCharacter = false; |
| break; |
| } |
| } |
| } |
|
|
| |
| if (isMissingCharacter && TMP_Settings.defaultFontAsset != null) |
| { |
| TMP_FontAsset fallback = TMP_Settings.defaultFontAsset; |
| int fallbackID = fallback.GetInstanceID(); |
|
|
| |
| if (k_SearchedFontAssetLookup.Add(fallbackID)) |
| { |
| if (fallback.HasCharacter_Internal(character, true, tryAddCharacter)) |
| isMissingCharacter = false; |
| } |
| } |
| } |
|
|
| if (isMissingCharacter) |
| s_MissingCharacterList.Add(character); |
| } |
|
|
| if (s_MissingCharacterList.Count > 0) |
| { |
| missingCharacters = s_MissingCharacterList.ToArray(); |
| return false; |
| } |
|
|
| return true; |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| public bool HasCharacters(string text) |
| { |
| if (m_CharacterLookupDictionary == null) |
| return false; |
|
|
| for (int i = 0; i < text.Length; i++) |
| { |
| if (!m_CharacterLookupDictionary.ContainsKey(text[i])) |
| return false; |
| } |
|
|
| return true; |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| public static string GetCharacters(TMP_FontAsset fontAsset) |
| { |
| string characters = string.Empty; |
|
|
| for (int i = 0; i < fontAsset.characterTable.Count; i++) |
| { |
| characters += (char)fontAsset.characterTable[i].unicode; |
| } |
|
|
| return characters; |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| public static int[] GetCharactersArray(TMP_FontAsset fontAsset) |
| { |
| int[] characters = new int[fontAsset.characterTable.Count]; |
|
|
| for (int i = 0; i < fontAsset.characterTable.Count; i++) |
| { |
| characters[i] = (int)fontAsset.characterTable[i].unicode; |
| } |
|
|
| return characters; |
| } |
|
|
| |
| |
| |
| |
| |
| internal uint GetGlyphIndex(uint unicode) |
| { |
| |
| if (m_CharacterLookupDictionary.ContainsKey(unicode)) |
| return m_CharacterLookupDictionary[unicode].glyphIndex; |
|
|
| |
| if (FontEngine.LoadFontFace(sourceFontFile, m_FaceInfo.pointSize) != FontEngineError.Success) |
| return 0; |
|
|
| return FontEngine.GetGlyphIndex(unicode); |
| } |
|
|
| |
| |
| |
| |
|
|
| |
| private static List<TMP_FontAsset> k_FontAssets_FontFeaturesUpdateQueue = new List<TMP_FontAsset>(); |
| private static HashSet<int> k_FontAssets_FontFeaturesUpdateQueueLookup = new HashSet<int>(); |
|
|
| private static List<TMP_FontAsset> k_FontAssets_AtlasTexturesUpdateQueue = new List<TMP_FontAsset>(); |
| private static HashSet<int> k_FontAssets_AtlasTexturesUpdateQueueLookup = new HashSet<int>(); |
|
|
| |
| |
| |
| |
| internal static void RegisterFontAssetForFontFeatureUpdate(TMP_FontAsset fontAsset) |
| { |
| int instanceID = fontAsset.instanceID; |
|
|
| if (k_FontAssets_FontFeaturesUpdateQueueLookup.Add(instanceID)) |
| k_FontAssets_FontFeaturesUpdateQueue.Add(fontAsset); |
| } |
|
|
| |
| |
| |
| |
| internal static void UpdateFontFeaturesForFontAssetsInQueue() |
| { |
| int count = k_FontAssets_FontFeaturesUpdateQueue.Count; |
|
|
| for (int i = 0; i < count; i++) |
| k_FontAssets_FontFeaturesUpdateQueue[i].UpdateGlyphAdjustmentRecords(); |
|
|
| if (count > 0) |
| { |
| k_FontAssets_FontFeaturesUpdateQueue.Clear(); |
| k_FontAssets_FontFeaturesUpdateQueueLookup.Clear(); |
| } |
| } |
|
|
| |
| |
| |
| |
| internal static void RegisterFontAssetForAtlasTextureUpdate(TMP_FontAsset fontAsset) |
| { |
| int instanceID = fontAsset.instanceID; |
|
|
| if (k_FontAssets_AtlasTexturesUpdateQueueLookup.Add(instanceID)) |
| k_FontAssets_AtlasTexturesUpdateQueue.Add(fontAsset); |
| } |
|
|
| |
| |
| |
| internal static void UpdateAtlasTexturesForFontAssetsInQueue() |
| { |
| int count = k_FontAssets_AtlasTexturesUpdateQueueLookup.Count; |
|
|
| for (int i = 0; i < count; i++) |
| k_FontAssets_AtlasTexturesUpdateQueue[i].TryAddGlyphsToAtlasTextures(); |
|
|
| if (count > 0) |
| { |
| k_FontAssets_AtlasTexturesUpdateQueue.Clear(); |
| k_FontAssets_AtlasTexturesUpdateQueueLookup.Clear(); |
| } |
| } |
|
|
| |
| |
| |
| |
|
|
| |
| |
| |
| private List<Glyph> m_GlyphsToRender = new List<Glyph>(); |
|
|
| |
| |
| |
| private List<Glyph> m_GlyphsRendered = new List<Glyph>(); |
|
|
| |
| |
| |
| private List<uint> m_GlyphIndexList = new List<uint>(); |
|
|
| |
| |
| |
| |
| private List<uint> m_GlyphIndexListNewlyAdded = new List<uint>(); |
|
|
| |
| |
| |
| internal List<uint> m_GlyphsToAdd = new List<uint>(); |
| internal HashSet<uint> m_GlyphsToAddLookup = new HashSet<uint>(); |
|
|
| internal List<TMP_Character> m_CharactersToAdd = new List<TMP_Character>(); |
| internal HashSet<uint> m_CharactersToAddLookup = new HashSet<uint>(); |
|
|
| |
| |
| |
| internal List<uint> s_MissingCharacterList = new List<uint>(); |
|
|
| |
| |
| |
| internal HashSet<uint> m_MissingUnicodesFromFontFile = new HashSet<uint>(); |
|
|
| |
| |
| |
| internal static uint[] k_GlyphIndexArray; |
|
|
| |
| |
| |
| |
| |
| |
| public bool TryAddCharacters(uint[] unicodes, bool includeFontFeatures = false) |
| { |
| uint[] missingUnicodes; |
|
|
| return TryAddCharacters(unicodes, out missingUnicodes, includeFontFeatures); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| public bool TryAddCharacters(uint[] unicodes, out uint[] missingUnicodes, bool includeFontFeatures = false) |
| { |
| k_TryAddCharactersMarker.Begin(); |
|
|
| |
| if (unicodes == null || unicodes.Length == 0 || m_AtlasPopulationMode == AtlasPopulationMode.Static) |
| { |
| if (m_AtlasPopulationMode == AtlasPopulationMode.Static) |
| Debug.LogWarning("Unable to add characters to font asset [" + this.name + "] because its AtlasPopulationMode is set to Static.", this); |
| else |
| Debug.LogWarning("Unable to add characters to font asset [" + this.name + "] because the provided Unicode list is Null or Empty.", this); |
|
|
| missingUnicodes = null; |
| k_TryAddCharactersMarker.End(); |
| return false; |
| } |
|
|
| |
| if (FontEngine.LoadFontFace(m_SourceFontFile, m_FaceInfo.pointSize) != FontEngineError.Success) |
| { |
| missingUnicodes = unicodes.ToArray(); |
| k_TryAddCharactersMarker.End(); |
| return false; |
| } |
|
|
| |
| if (m_CharacterLookupDictionary == null || m_GlyphLookupDictionary == null) |
| ReadFontAssetDefinition(); |
|
|
| |
| m_GlyphsToAdd.Clear(); |
| m_GlyphsToAddLookup.Clear(); |
| m_CharactersToAdd.Clear(); |
| m_CharactersToAddLookup.Clear(); |
| s_MissingCharacterList.Clear(); |
|
|
| bool isMissingCharacters = false; |
| int unicodeCount = unicodes.Length; |
|
|
| for (int i = 0; i < unicodeCount; i++) |
| { |
| uint unicode = unicodes[i]; |
|
|
| |
| if (m_CharacterLookupDictionary.ContainsKey(unicode)) |
| continue; |
|
|
| |
| uint glyphIndex = FontEngine.GetGlyphIndex(unicode); |
|
|
| |
| if (glyphIndex == 0) |
| { |
| |
| switch (unicode) |
| { |
| case 0xA0: |
| |
| glyphIndex = FontEngine.GetGlyphIndex(0x20); |
| break; |
| case 0xAD: |
| case 0x2011: |
| |
| glyphIndex = FontEngine.GetGlyphIndex(0x2D); |
| break; |
| } |
|
|
| |
| if (glyphIndex == 0) |
| { |
| |
| s_MissingCharacterList.Add(unicode); |
|
|
| isMissingCharacters = true; |
| continue; |
| } |
| } |
|
|
| TMP_Character character = new TMP_Character(unicode, glyphIndex); |
|
|
| |
| if (m_GlyphLookupDictionary.ContainsKey(glyphIndex)) |
| { |
| |
| character.glyph = m_GlyphLookupDictionary[glyphIndex]; |
| character.textAsset = this; |
|
|
| m_CharacterTable.Add(character); |
| m_CharacterLookupDictionary.Add(unicode, character); |
| continue; |
| } |
|
|
| |
| if (m_GlyphsToAddLookup.Add(glyphIndex)) |
| m_GlyphsToAdd.Add(glyphIndex); |
|
|
| |
| if (m_CharactersToAddLookup.Add(unicode)) |
| m_CharactersToAdd.Add(character); |
| } |
|
|
| if (m_GlyphsToAdd.Count == 0) |
| { |
| |
| missingUnicodes = unicodes; |
| k_TryAddCharactersMarker.End(); |
| return false; |
| } |
|
|
| |
| if (m_AtlasTextures[m_AtlasTextureIndex].width == 0 || m_AtlasTextures[m_AtlasTextureIndex].height == 0) |
| { |
| m_AtlasTextures[m_AtlasTextureIndex].Resize(m_AtlasWidth, m_AtlasHeight); |
| FontEngine.ResetAtlasTexture(m_AtlasTextures[m_AtlasTextureIndex]); |
| } |
|
|
| Glyph[] glyphs; |
| bool allGlyphsAddedToTexture = FontEngine.TryAddGlyphsToTexture(m_GlyphsToAdd, m_AtlasPadding, GlyphPackingMode.BestShortSideFit, m_FreeGlyphRects, m_UsedGlyphRects, m_AtlasRenderMode, m_AtlasTextures[m_AtlasTextureIndex], out glyphs); |
|
|
| |
| for (int i = 0; i < glyphs.Length && glyphs[i] != null; i++) |
| { |
| Glyph glyph = glyphs[i]; |
| uint glyphIndex = glyph.index; |
|
|
| glyph.atlasIndex = m_AtlasTextureIndex; |
|
|
| |
| m_GlyphTable.Add(glyph); |
| m_GlyphLookupDictionary.Add(glyphIndex, glyph); |
|
|
| m_GlyphIndexListNewlyAdded.Add(glyphIndex); |
| m_GlyphIndexList.Add(glyphIndex); |
| } |
|
|
| |
| m_GlyphsToAdd.Clear(); |
|
|
| |
| for (int i = 0; i < m_CharactersToAdd.Count; i++) |
| { |
| TMP_Character character = m_CharactersToAdd[i]; |
| Glyph glyph; |
|
|
| if (m_GlyphLookupDictionary.TryGetValue(character.glyphIndex, out glyph) == false) |
| { |
| m_GlyphsToAdd.Add(character.glyphIndex); |
| continue; |
| } |
|
|
| |
| character.glyph = glyph; |
| character.textAsset = this; |
|
|
| m_CharacterTable.Add(character); |
| m_CharacterLookupDictionary.Add(character.unicode, character); |
|
|
| |
| m_CharactersToAdd.RemoveAt(i); |
| i -= 1; |
| } |
|
|
| |
| if (m_IsMultiAtlasTexturesEnabled && allGlyphsAddedToTexture == false) |
| { |
| while (allGlyphsAddedToTexture == false) |
| allGlyphsAddedToTexture = TryAddGlyphsToNewAtlasTexture(); |
| } |
|
|
| |
| if (includeFontFeatures) |
| UpdateGlyphAdjustmentRecords(); |
|
|
| #if UNITY_EDITOR |
| |
| if (UnityEditor.EditorUtility.IsPersistent(this)) |
| { |
| TMP_EditorResourceManager.RegisterResourceForUpdate(this); |
| } |
| #endif |
|
|
| |
| for (int i = 0; i < m_CharactersToAdd.Count; i++) |
| { |
| TMP_Character character = m_CharactersToAdd[i]; |
| s_MissingCharacterList.Add(character.unicode); |
| } |
|
|
| missingUnicodes = null; |
|
|
| if (s_MissingCharacterList.Count > 0) |
| missingUnicodes = s_MissingCharacterList.ToArray(); |
|
|
| k_TryAddCharactersMarker.End(); |
|
|
| return allGlyphsAddedToTexture && !isMissingCharacters; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| public bool TryAddCharacters(string characters, bool includeFontFeatures = false) |
| { |
| string missingCharacters; |
|
|
| return TryAddCharacters(characters, out missingCharacters, includeFontFeatures); |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| public bool TryAddCharacters(string characters, out string missingCharacters, bool includeFontFeatures = false) |
| { |
| k_TryAddCharactersMarker.Begin(); |
|
|
| |
| if (string.IsNullOrEmpty(characters) || m_AtlasPopulationMode == AtlasPopulationMode.Static) |
| { |
| if (m_AtlasPopulationMode == AtlasPopulationMode.Static) |
| Debug.LogWarning("Unable to add characters to font asset [" + this.name + "] because its AtlasPopulationMode is set to Static.", this); |
| else |
| { |
| Debug.LogWarning("Unable to add characters to font asset [" + this.name + "] because the provided character list is Null or Empty.", this); |
| } |
|
|
| missingCharacters = characters; |
| k_TryAddCharactersMarker.End(); |
| return false; |
| } |
|
|
| |
| if (FontEngine.LoadFontFace(m_SourceFontFile, m_FaceInfo.pointSize) != FontEngineError.Success) |
| { |
| missingCharacters = characters; |
| k_TryAddCharactersMarker.End(); |
| return false; |
| } |
|
|
| |
| if (m_CharacterLookupDictionary == null || m_GlyphLookupDictionary == null) |
| ReadFontAssetDefinition(); |
|
|
| |
| m_GlyphsToAdd.Clear(); |
| m_GlyphsToAddLookup.Clear(); |
| m_CharactersToAdd.Clear(); |
| m_CharactersToAddLookup.Clear(); |
| s_MissingCharacterList.Clear(); |
|
|
| bool isMissingCharacters = false; |
| int characterCount = characters.Length; |
|
|
| |
| for (int i = 0; i < characterCount; i++) |
| { |
| uint unicode = characters[i]; |
|
|
| |
| if (m_CharacterLookupDictionary.ContainsKey(unicode)) |
| continue; |
|
|
| |
| uint glyphIndex = FontEngine.GetGlyphIndex(unicode); |
|
|
| |
| if (glyphIndex == 0) |
| { |
| |
| switch (unicode) |
| { |
| case 0xA0: |
| |
| glyphIndex = FontEngine.GetGlyphIndex(0x20); |
| break; |
| case 0xAD: |
| case 0x2011: |
| |
| glyphIndex = FontEngine.GetGlyphIndex(0x2D); |
| break; |
| } |
|
|
| |
| if (glyphIndex == 0) |
| { |
| |
| s_MissingCharacterList.Add(unicode); |
|
|
| isMissingCharacters = true; |
| continue; |
| } |
| } |
|
|
| TMP_Character character = new TMP_Character(unicode, glyphIndex); |
|
|
| |
| if (m_GlyphLookupDictionary.ContainsKey(glyphIndex)) |
| { |
| |
| character.glyph = m_GlyphLookupDictionary[glyphIndex]; |
| character.textAsset = this; |
|
|
| m_CharacterTable.Add(character); |
| m_CharacterLookupDictionary.Add(unicode, character); |
| continue; |
| } |
|
|
| |
| if (m_GlyphsToAddLookup.Add(glyphIndex)) |
| m_GlyphsToAdd.Add(glyphIndex); |
|
|
| |
| if (m_CharactersToAddLookup.Add(unicode)) |
| m_CharactersToAdd.Add(character); |
| } |
|
|
| if (m_GlyphsToAdd.Count == 0) |
| { |
| missingCharacters = characters; |
| k_TryAddCharactersMarker.End(); |
| return false; |
| } |
|
|
| |
| if (m_AtlasTextures[m_AtlasTextureIndex].width == 0 || m_AtlasTextures[m_AtlasTextureIndex].height == 0) |
| { |
| |
| m_AtlasTextures[m_AtlasTextureIndex].Resize(m_AtlasWidth, m_AtlasHeight); |
| FontEngine.ResetAtlasTexture(m_AtlasTextures[m_AtlasTextureIndex]); |
| } |
|
|
| Glyph[] glyphs; |
|
|
| bool allGlyphsAddedToTexture = FontEngine.TryAddGlyphsToTexture(m_GlyphsToAdd, m_AtlasPadding, GlyphPackingMode.BestShortSideFit, m_FreeGlyphRects, m_UsedGlyphRects, m_AtlasRenderMode, m_AtlasTextures[m_AtlasTextureIndex], out glyphs); |
|
|
| for (int i = 0; i < glyphs.Length && glyphs[i] != null; i++) |
| { |
| Glyph glyph = glyphs[i]; |
| uint glyphIndex = glyph.index; |
|
|
| glyph.atlasIndex = m_AtlasTextureIndex; |
|
|
| |
| m_GlyphTable.Add(glyph); |
| m_GlyphLookupDictionary.Add(glyphIndex, glyph); |
|
|
| m_GlyphIndexListNewlyAdded.Add(glyphIndex); |
| m_GlyphIndexList.Add(glyphIndex); |
| } |
|
|
| |
| m_GlyphsToAdd.Clear(); |
|
|
| |
| for (int i = 0; i < m_CharactersToAdd.Count; i++) |
| { |
| TMP_Character character = m_CharactersToAdd[i]; |
| Glyph glyph; |
|
|
| if (m_GlyphLookupDictionary.TryGetValue(character.glyphIndex, out glyph) == false) |
| { |
| m_GlyphsToAdd.Add(character.glyphIndex); |
| continue; |
| } |
|
|
| |
| character.glyph = glyph; |
| character.textAsset = this; |
|
|
| m_CharacterTable.Add(character); |
| m_CharacterLookupDictionary.Add(character.unicode, character); |
|
|
| |
| m_CharactersToAdd.RemoveAt(i); |
| i -= 1; |
| } |
|
|
| |
| if (m_IsMultiAtlasTexturesEnabled && allGlyphsAddedToTexture == false) |
| { |
| while (allGlyphsAddedToTexture == false) |
| allGlyphsAddedToTexture = TryAddGlyphsToNewAtlasTexture(); |
| } |
|
|
| |
| if (includeFontFeatures) |
| UpdateGlyphAdjustmentRecords(); |
|
|
| #if UNITY_EDITOR |
| |
| if (UnityEditor.EditorUtility.IsPersistent(this)) |
| { |
| TMP_EditorResourceManager.RegisterResourceForUpdate(this); |
| } |
| #endif |
|
|
| missingCharacters = string.Empty; |
|
|
| |
| for (int i = 0; i < m_CharactersToAdd.Count; i++) |
| { |
| TMP_Character character = m_CharactersToAdd[i]; |
| s_MissingCharacterList.Add(character.unicode); |
| } |
|
|
| if (s_MissingCharacterList.Count > 0) |
| missingCharacters = s_MissingCharacterList.UintToString(); |
|
|
| k_TryAddCharactersMarker.End(); |
| return allGlyphsAddedToTexture && !isMissingCharacters; |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| internal bool TryAddCharacterInternal(uint unicode, out TMP_Character character) |
| { |
| k_TryAddCharacterMarker.Begin(); |
|
|
| character = null; |
|
|
| |
| if (m_MissingUnicodesFromFontFile.Contains(unicode)) |
| { |
| k_TryAddCharacterMarker.End(); |
| return false; |
| } |
|
|
| |
| if (FontEngine.LoadFontFace(sourceFontFile, m_FaceInfo.pointSize) != FontEngineError.Success) |
| { |
| k_TryAddCharacterMarker.End(); |
| return false; |
| } |
|
|
| uint glyphIndex = FontEngine.GetGlyphIndex(unicode); |
| if (glyphIndex == 0) |
| { |
| |
| switch (unicode) |
| { |
| case 0xA0: |
| |
| glyphIndex = FontEngine.GetGlyphIndex(0x20); |
| break; |
| case 0xAD: |
| case 0x2011: |
| |
| glyphIndex = FontEngine.GetGlyphIndex(0x2D); |
| break; |
| } |
|
|
| |
| if (glyphIndex == 0) |
| { |
| m_MissingUnicodesFromFontFile.Add(unicode); |
|
|
| k_TryAddCharacterMarker.End(); |
| return false; |
| } |
| } |
|
|
| |
| if (m_GlyphLookupDictionary.ContainsKey(glyphIndex)) |
| { |
| character = new TMP_Character(unicode, this, m_GlyphLookupDictionary[glyphIndex]); |
| m_CharacterTable.Add(character); |
| m_CharacterLookupDictionary.Add(unicode, character); |
|
|
| #if UNITY_EDITOR |
| |
| |
| |
| |
| if (UnityEditor.EditorUtility.IsPersistent(this)) |
| { |
| TMP_EditorResourceManager.RegisterResourceForUpdate(this); |
| } |
| #endif |
|
|
| k_TryAddCharacterMarker.End(); |
| return true; |
| } |
|
|
| Glyph glyph = null; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
|
|
| |
|
|
| |
| |
| |
| |
| |
|
|
| |
| |
| |
|
|
| |
| if (m_AtlasTextures[m_AtlasTextureIndex].isReadable == false) |
| { |
| Debug.LogWarning("Unable to add the requested character to font asset [" + this.name + "]'s atlas texture. Please make the texture [" + m_AtlasTextures[m_AtlasTextureIndex].name + "] readable.", m_AtlasTextures[m_AtlasTextureIndex]); |
|
|
| k_TryAddCharacterMarker.End(); |
| return false; |
| } |
|
|
| |
| if (m_AtlasTextures[m_AtlasTextureIndex].width == 0 || m_AtlasTextures[m_AtlasTextureIndex].height == 0) |
| { |
| m_AtlasTextures[m_AtlasTextureIndex].Resize(m_AtlasWidth, m_AtlasHeight); |
| FontEngine.ResetAtlasTexture(m_AtlasTextures[m_AtlasTextureIndex]); |
| } |
|
|
| |
| if (FontEngine.TryAddGlyphToTexture(glyphIndex, m_AtlasPadding, GlyphPackingMode.BestShortSideFit, m_FreeGlyphRects, m_UsedGlyphRects, m_AtlasRenderMode, m_AtlasTextures[m_AtlasTextureIndex], out glyph)) |
| { |
| |
| glyph.atlasIndex = m_AtlasTextureIndex; |
|
|
| |
| m_GlyphTable.Add(glyph); |
| m_GlyphLookupDictionary.Add(glyphIndex, glyph); |
|
|
| |
| character = new TMP_Character(unicode, this, glyph); |
| m_CharacterTable.Add(character); |
| m_CharacterLookupDictionary.Add(unicode, character); |
|
|
| m_GlyphIndexList.Add(glyphIndex); |
| m_GlyphIndexListNewlyAdded.Add(glyphIndex); |
|
|
| if (TMP_Settings.getFontFeaturesAtRuntime) |
| RegisterFontAssetForFontFeatureUpdate(this); |
|
|
| #if UNITY_EDITOR |
| |
| |
| |
| |
| if (UnityEditor.EditorUtility.IsPersistent(this)) |
| { |
| TMP_EditorResourceManager.RegisterResourceForUpdate(this); |
| } |
| #endif |
|
|
| k_TryAddCharacterMarker.End(); |
| return true; |
| } |
|
|
| |
| if (m_IsMultiAtlasTexturesEnabled) |
| { |
| |
| SetupNewAtlasTexture(); |
|
|
| |
| if (FontEngine.TryAddGlyphToTexture(glyphIndex, m_AtlasPadding, GlyphPackingMode.BestShortSideFit, m_FreeGlyphRects, m_UsedGlyphRects, m_AtlasRenderMode, m_AtlasTextures[m_AtlasTextureIndex], out glyph)) |
| { |
| |
| glyph.atlasIndex = m_AtlasTextureIndex; |
|
|
| |
| m_GlyphTable.Add(glyph); |
| m_GlyphLookupDictionary.Add(glyphIndex, glyph); |
|
|
| |
| character = new TMP_Character(unicode, this, glyph); |
| m_CharacterTable.Add(character); |
| m_CharacterLookupDictionary.Add(unicode, character); |
|
|
| m_GlyphIndexList.Add(glyphIndex); |
| m_GlyphIndexListNewlyAdded.Add(glyphIndex); |
|
|
| if (TMP_Settings.getFontFeaturesAtRuntime) |
| RegisterFontAssetForFontFeatureUpdate(this); |
|
|
| #if UNITY_EDITOR |
| |
| if (UnityEditor.EditorUtility.IsPersistent(this)) |
| { |
| TMP_EditorResourceManager.RegisterResourceForUpdate(this); |
| } |
| #endif |
|
|
| k_TryAddCharacterMarker.End(); |
| return true; |
| } |
| } |
|
|
| k_TryAddCharacterMarker.End(); |
|
|
| return false; |
| } |
|
|
|
|
| internal bool TryGetCharacter_and_QueueRenderToTexture(uint unicode, out TMP_Character character) |
| { |
| k_TryAddCharacterMarker.Begin(); |
|
|
| character = null; |
|
|
| |
| if (m_MissingUnicodesFromFontFile.Contains(unicode)) |
| { |
| k_TryAddCharacterMarker.End(); |
| return false; |
| } |
|
|
| |
| if (FontEngine.LoadFontFace(sourceFontFile, m_FaceInfo.pointSize) != FontEngineError.Success) |
| { |
| k_TryAddCharacterMarker.End(); |
| return false; |
| } |
|
|
| uint glyphIndex = FontEngine.GetGlyphIndex(unicode); |
| if (glyphIndex == 0) |
| { |
| |
| switch (unicode) |
| { |
| case 0xA0: |
| |
| glyphIndex = FontEngine.GetGlyphIndex(0x20); |
| break; |
| case 0xAD: |
| case 0x2011: |
| |
| glyphIndex = FontEngine.GetGlyphIndex(0x2D); |
| break; |
| } |
|
|
| |
| if (glyphIndex == 0) |
| { |
| m_MissingUnicodesFromFontFile.Add(unicode); |
|
|
| k_TryAddCharacterMarker.End(); |
| return false; |
| } |
| } |
|
|
| |
| if (m_GlyphLookupDictionary.ContainsKey(glyphIndex)) |
| { |
| character = new TMP_Character(unicode, this, m_GlyphLookupDictionary[glyphIndex]); |
| m_CharacterTable.Add(character); |
| m_CharacterLookupDictionary.Add(unicode, character); |
|
|
| #if UNITY_EDITOR |
| |
| |
| |
| |
| if (UnityEditor.EditorUtility.IsPersistent(this)) |
| { |
| TMP_EditorResourceManager.RegisterResourceForUpdate(this); |
| } |
| #endif |
|
|
| k_TryAddCharacterMarker.End(); |
| return true; |
| } |
|
|
| GlyphLoadFlags glyphLoadFlags = (GlyphRasterModes.RASTER_MODE_NO_HINTING & (GlyphRasterModes)m_AtlasRenderMode) == GlyphRasterModes.RASTER_MODE_NO_HINTING |
| ? GlyphLoadFlags.LOAD_NO_BITMAP | GlyphLoadFlags.LOAD_NO_HINTING |
| : GlyphLoadFlags.LOAD_NO_BITMAP; |
|
|
| Glyph glyph = null; |
|
|
| if (FontEngine.TryGetGlyphWithIndexValue(glyphIndex, glyphLoadFlags, out glyph)) |
| { |
| |
| m_GlyphTable.Add(glyph); |
| m_GlyphLookupDictionary.Add(glyphIndex, glyph); |
|
|
| |
| character = new TMP_Character(unicode, this, glyph); |
| m_CharacterTable.Add(character); |
| m_CharacterLookupDictionary.Add(unicode, character); |
|
|
| m_GlyphIndexList.Add(glyphIndex); |
| m_GlyphIndexListNewlyAdded.Add(glyphIndex); |
|
|
| if (TMP_Settings.getFontFeaturesAtRuntime) |
| RegisterFontAssetForFontFeatureUpdate(this); |
|
|
| |
| m_GlyphsToRender.Add(glyph); |
|
|
| |
| RegisterFontAssetForAtlasTextureUpdate(this); |
|
|
| #if UNITY_EDITOR |
| |
| |
| |
| |
| if (UnityEditor.EditorUtility.IsPersistent(this)) |
| { |
| TMP_EditorResourceManager.RegisterResourceForUpdate(this); |
| } |
| #endif |
|
|
| k_TryAddCharacterMarker.End(); |
| return true; |
| } |
|
|
| k_TryAddCharacterMarker.End(); |
| return false; |
| } |
|
|
| |
| |
| |
| internal void TryAddGlyphsToAtlasTextures() |
| { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| } |
|
|
|
|
| |
| |
| |
| |
| bool TryAddGlyphsToNewAtlasTexture() |
| { |
| |
| SetupNewAtlasTexture(); |
|
|
| Glyph[] glyphs; |
|
|
| |
| bool allGlyphsAddedToTexture = FontEngine.TryAddGlyphsToTexture(m_GlyphsToAdd, m_AtlasPadding, GlyphPackingMode.BestShortSideFit, m_FreeGlyphRects, m_UsedGlyphRects, m_AtlasRenderMode, m_AtlasTextures[m_AtlasTextureIndex], out glyphs); |
|
|
| |
| for (int i = 0; i < glyphs.Length && glyphs[i] != null; i++) |
| { |
| Glyph glyph = glyphs[i]; |
| uint glyphIndex = glyph.index; |
|
|
| glyph.atlasIndex = m_AtlasTextureIndex; |
|
|
| |
| m_GlyphTable.Add(glyph); |
| m_GlyphLookupDictionary.Add(glyphIndex, glyph); |
|
|
| m_GlyphIndexListNewlyAdded.Add(glyphIndex); |
| m_GlyphIndexList.Add(glyphIndex); |
| } |
|
|
| |
| m_GlyphsToAdd.Clear(); |
|
|
| |
| for (int i = 0; i < m_CharactersToAdd.Count; i++) |
| { |
| TMP_Character character = m_CharactersToAdd[i]; |
| Glyph glyph; |
|
|
| if (m_GlyphLookupDictionary.TryGetValue(character.glyphIndex, out glyph) == false) |
| { |
| m_GlyphsToAdd.Add(character.glyphIndex); |
| continue; |
| } |
|
|
| |
| character.glyph = glyph; |
| character.textAsset = this; |
|
|
| m_CharacterTable.Add(character); |
| m_CharacterLookupDictionary.Add(character.unicode, character); |
|
|
| |
| m_CharactersToAdd.RemoveAt(i); |
| i -= 1; |
| } |
|
|
| return allGlyphsAddedToTexture; |
| } |
|
|
|
|
| |
| |
| |
| void SetupNewAtlasTexture() |
| { |
| m_AtlasTextureIndex += 1; |
|
|
| |
| if (m_AtlasTextures.Length == m_AtlasTextureIndex) |
| Array.Resize(ref m_AtlasTextures, m_AtlasTextures.Length * 2); |
|
|
| |
| m_AtlasTextures[m_AtlasTextureIndex] = new Texture2D(m_AtlasWidth, m_AtlasHeight, TextureFormat.Alpha8, false); |
| FontEngine.ResetAtlasTexture(m_AtlasTextures[m_AtlasTextureIndex]); |
|
|
| |
| int packingModifier = ((GlyphRasterModes)m_AtlasRenderMode & GlyphRasterModes.RASTER_MODE_BITMAP) == GlyphRasterModes.RASTER_MODE_BITMAP ? 0 : 1; |
| m_FreeGlyphRects.Clear(); |
| m_FreeGlyphRects.Add(new GlyphRect(0, 0, m_AtlasWidth - packingModifier, m_AtlasHeight - packingModifier)); |
| m_UsedGlyphRects.Clear(); |
|
|
| #if UNITY_EDITOR |
| |
| if (UnityEditor.EditorUtility.IsPersistent(this)) |
| { |
| Texture2D tex = m_AtlasTextures[m_AtlasTextureIndex]; |
| tex.name = m_AtlasTexture.name + " " + m_AtlasTextureIndex; |
|
|
| UnityEditor.AssetDatabase.AddObjectToAsset(m_AtlasTextures[m_AtlasTextureIndex], this); |
| TMP_EditorResourceManager.RegisterResourceForReimport(this); |
| } |
| #endif |
| } |
|
|
|
|
| |
| |
| |
| internal void UpdateAtlasTexture() |
| { |
| |
| if (m_GlyphsToRender.Count == 0) |
| return; |
|
|
| |
|
|
| |
| |
| |
| |
|
|
| |
| if (m_AtlasTextures[m_AtlasTextureIndex].width == 0 || m_AtlasTextures[m_AtlasTextureIndex].height == 0) |
| { |
| |
| m_AtlasTextures[m_AtlasTextureIndex].Resize(m_AtlasWidth, m_AtlasHeight); |
| FontEngine.ResetAtlasTexture(m_AtlasTextures[m_AtlasTextureIndex]); |
| } |
|
|
| |
|
|
| |
| m_AtlasTextures[m_AtlasTextureIndex].Apply(false, false); |
|
|
| |
| |
| |
| |
|
|
| |
| |
|
|
| |
| |
| |
|
|
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| #if UNITY_EDITOR |
| |
| |
| TMP_EditorResourceManager.RegisterResourceForUpdate(this); |
| #endif |
| } |
|
|
| |
| |
| |
| internal void UpdateGlyphAdjustmentRecords() |
| { |
| k_UpdateGlyphAdjustmentRecordsMarker.Begin(); |
|
|
| |
| #if UNITY_2018_3 || UNITY_2019_1 || UNITY_2019_2 || UNITY_2019_3 |
| CopyListDataToArray(m_GlyphIndexList, ref k_GlyphIndexArray); |
| GlyphPairAdjustmentRecord[] pairAdjustmentRecords = FontEngine.GetGlyphPairAdjustmentTable(k_GlyphIndexArray); |
| #else |
| |
| GlyphPairAdjustmentRecord[] pairAdjustmentRecords = FontEngine.GetGlyphPairAdjustmentRecords(m_GlyphIndexList, out int recordCount); |
| #endif |
|
|
| |
| m_GlyphIndexListNewlyAdded.Clear(); |
|
|
| if (pairAdjustmentRecords == null || pairAdjustmentRecords.Length == 0) |
| { |
| k_UpdateGlyphAdjustmentRecordsMarker.End(); |
| return; |
| } |
|
|
| if (m_FontFeatureTable == null) |
| m_FontFeatureTable = new TMP_FontFeatureTable(); |
|
|
| for (int i = 0; i < pairAdjustmentRecords.Length && pairAdjustmentRecords[i].firstAdjustmentRecord.glyphIndex != 0; i++) |
| { |
| uint pairKey = pairAdjustmentRecords[i].secondAdjustmentRecord.glyphIndex << 16 | pairAdjustmentRecords[i].firstAdjustmentRecord.glyphIndex; |
|
|
| |
| if (m_FontFeatureTable.m_GlyphPairAdjustmentRecordLookupDictionary.ContainsKey(pairKey)) |
| continue; |
|
|
| TMP_GlyphPairAdjustmentRecord record = new TMP_GlyphPairAdjustmentRecord(pairAdjustmentRecords[i]); |
|
|
| m_FontFeatureTable.m_GlyphPairAdjustmentRecords.Add(record); |
| m_FontFeatureTable.m_GlyphPairAdjustmentRecordLookupDictionary.Add(pairKey, record); |
| } |
|
|
| k_UpdateGlyphAdjustmentRecordsMarker.End(); |
| } |
|
|
| |
| |
| |
| |
| internal void UpdateGlyphAdjustmentRecords(uint[] glyphIndexes) |
| { |
| k_UpdateGlyphAdjustmentRecordsMarker.Begin(); |
|
|
| |
| GlyphPairAdjustmentRecord[] pairAdjustmentRecords = FontEngine.GetGlyphPairAdjustmentTable(glyphIndexes); |
|
|
| |
| |
|
|
| if (pairAdjustmentRecords == null || pairAdjustmentRecords.Length == 0) |
| { |
| k_UpdateGlyphAdjustmentRecordsMarker.End(); |
| return; |
| } |
|
|
| if (m_FontFeatureTable == null) |
| m_FontFeatureTable = new TMP_FontFeatureTable(); |
|
|
| for (int i = 0; i < pairAdjustmentRecords.Length && pairAdjustmentRecords[i].firstAdjustmentRecord.glyphIndex != 0; i++) |
| { |
| uint pairKey = pairAdjustmentRecords[i].secondAdjustmentRecord.glyphIndex << 16 | pairAdjustmentRecords[i].firstAdjustmentRecord.glyphIndex; |
|
|
| |
| if (m_FontFeatureTable.m_GlyphPairAdjustmentRecordLookupDictionary.ContainsKey(pairKey)) |
| continue; |
|
|
| TMP_GlyphPairAdjustmentRecord record = new TMP_GlyphPairAdjustmentRecord(pairAdjustmentRecords[i]); |
|
|
| m_FontFeatureTable.m_GlyphPairAdjustmentRecords.Add(record); |
| m_FontFeatureTable.m_GlyphPairAdjustmentRecordLookupDictionary.Add(pairKey, record); |
| } |
|
|
| k_UpdateGlyphAdjustmentRecordsMarker.End(); |
| } |
|
|
| |
| |
| |
| |
| internal void UpdateGlyphAdjustmentRecords(List<uint> glyphIndexes) |
| { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| } |
|
|
| |
| |
| |
| |
| |
| internal void UpdateGlyphAdjustmentRecords(List<uint> newGlyphIndexes, List<uint> allGlyphIndexes) |
| { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| } |
|
|
| |
| |
| |
| |
| |
| |
| void CopyListDataToArray<T>(List<T> srcList, ref T[] dstArray) |
| { |
| int size = srcList.Count; |
|
|
| |
| if (dstArray == null) |
| dstArray = new T[size]; |
| else |
| Array.Resize(ref dstArray, size); |
|
|
| for (int i = 0; i < size; i++) |
| dstArray[i] = srcList[i]; |
| } |
|
|
| |
| |
| |
| |
| |
| public void ClearFontAssetData(bool setAtlasSizeToZero = false) |
| { |
| k_ClearFontAssetDataMarker.Begin(); |
|
|
| #if UNITY_EDITOR |
| |
| |
| #endif |
|
|
| |
| ClearFontAssetTables(); |
|
|
| |
| ClearAtlasTextures(setAtlasSizeToZero); |
|
|
| ReadFontAssetDefinition(); |
|
|
| |
|
|
| #if UNITY_EDITOR |
| |
| TMP_EditorResourceManager.RegisterResourceForUpdate(this); |
| #endif |
|
|
| k_ClearFontAssetDataMarker.End(); |
| } |
|
|
| internal void ClearFontAssetDataInternal() |
| { |
| |
| ClearFontAssetTables(); |
|
|
| |
| ClearAtlasTextures(true); |
|
|
| #if UNITY_EDITOR |
| |
| TMP_EditorResourceManager.RegisterResourceForUpdate(this); |
| #endif |
| } |
|
|
| |
| |
| |
| internal void UpdateFontAssetData() |
| { |
| k_UpdateFontAssetDataMarker.Begin(); |
|
|
| |
| uint[] unicodeCharacters = new uint[m_CharacterTable.Count]; |
|
|
| for (int i = 0; i < m_CharacterTable.Count; i++) |
| unicodeCharacters[i] = m_CharacterTable[i].unicode; |
|
|
| |
| ClearFontAssetTables(); |
|
|
| |
| ClearAtlasTextures(true); |
|
|
| ReadFontAssetDefinition(); |
|
|
| |
|
|
| |
| if (unicodeCharacters.Length > 0) |
| TryAddCharacters(unicodeCharacters, true); |
|
|
| k_UpdateFontAssetDataMarker.End(); |
| } |
|
|
| |
| |
| |
| internal void ClearFontAssetTables() |
| { |
| |
| if (m_GlyphTable != null) |
| m_GlyphTable.Clear(); |
|
|
| if (m_CharacterTable != null) |
| m_CharacterTable.Clear(); |
|
|
| |
| if (m_UsedGlyphRects != null) |
| m_UsedGlyphRects.Clear(); |
|
|
| if (m_FreeGlyphRects != null) |
| { |
| int packingModifier = ((GlyphRasterModes)m_AtlasRenderMode & GlyphRasterModes.RASTER_MODE_BITMAP) == GlyphRasterModes.RASTER_MODE_BITMAP ? 0 : 1; |
| m_FreeGlyphRects.Clear(); |
| m_FreeGlyphRects.Add(new GlyphRect(0, 0, m_AtlasWidth - packingModifier, m_AtlasHeight - packingModifier)); |
| } |
|
|
| if (m_GlyphsToRender != null) |
| m_GlyphsToRender.Clear(); |
|
|
| if (m_GlyphsRendered != null) |
| m_GlyphsRendered.Clear(); |
|
|
| |
| if (m_FontFeatureTable != null && m_FontFeatureTable.m_GlyphPairAdjustmentRecords != null) |
| m_FontFeatureTable.glyphPairAdjustmentRecords.Clear(); |
| } |
|
|
| |
| |
| |
| |
| internal void ClearAtlasTextures(bool setAtlasSizeToZero = false) |
| { |
| m_AtlasTextureIndex = 0; |
|
|
| |
| if (m_AtlasTextures == null) |
| return; |
|
|
| Texture2D texture = null; |
|
|
| |
| for (int i = 1; i < m_AtlasTextures.Length; i++) |
| { |
| texture = m_AtlasTextures[i]; |
|
|
| if (texture == null) |
| continue; |
|
|
| DestroyImmediate(texture, true); |
|
|
| #if UNITY_EDITOR |
| if (UnityEditor.EditorUtility.IsPersistent(this)) |
| TMP_EditorResourceManager.RegisterResourceForReimport(this); |
| #endif |
| } |
|
|
| |
| Array.Resize(ref m_AtlasTextures, 1); |
|
|
| texture = m_AtlasTexture = m_AtlasTextures[0]; |
|
|
| |
| if (texture.isReadable == false) |
| { |
| #if UNITY_EDITOR && UNITY_2018_4_OR_NEWER && !UNITY_2018_4_0 && !UNITY_2018_4_1 && !UNITY_2018_4_2 && !UNITY_2018_4_3 && !UNITY_2018_4_4 |
| FontEngineEditorUtilities.SetAtlasTextureIsReadable(texture, true); |
| #else |
| Debug.LogWarning("Unable to reset font asset [" + this.name + "]'s atlas texture. Please make the texture [" + texture.name + "] readable.", texture); |
| return; |
| #endif |
| } |
|
|
| if (setAtlasSizeToZero) |
| { |
| texture.Resize(0, 0, TextureFormat.Alpha8, false); |
| } |
| else if (texture.width != m_AtlasWidth || texture.height != m_AtlasHeight) |
| { |
| texture.Resize(m_AtlasWidth, m_AtlasHeight, TextureFormat.Alpha8, false); |
| } |
|
|
| |
| FontEngine.ResetAtlasTexture(texture); |
| texture.Apply(); |
| } |
|
|
| |
| |
| |
| internal void UpgradeFontAsset() |
| { |
| m_Version = "1.1.0"; |
|
|
| Debug.Log("Upgrading font asset [" + this.name + "] to version " + m_Version + ".", this); |
|
|
| m_FaceInfo.familyName = m_fontInfo.Name; |
| m_FaceInfo.styleName = string.Empty; |
|
|
| m_FaceInfo.pointSize = (int)m_fontInfo.PointSize; |
| m_FaceInfo.scale = m_fontInfo.Scale; |
|
|
| m_FaceInfo.lineHeight = m_fontInfo.LineHeight; |
| m_FaceInfo.ascentLine = m_fontInfo.Ascender; |
| m_FaceInfo.capLine = m_fontInfo.CapHeight; |
| m_FaceInfo.meanLine = m_fontInfo.CenterLine; |
| m_FaceInfo.baseline = m_fontInfo.Baseline; |
| m_FaceInfo.descentLine = m_fontInfo.Descender; |
|
|
| m_FaceInfo.superscriptOffset = m_fontInfo.SuperscriptOffset; |
| m_FaceInfo.superscriptSize = m_fontInfo.SubSize; |
| m_FaceInfo.subscriptOffset = m_fontInfo.SubscriptOffset; |
| m_FaceInfo.subscriptSize = m_fontInfo.SubSize; |
|
|
| m_FaceInfo.underlineOffset = m_fontInfo.Underline; |
| m_FaceInfo.underlineThickness = m_fontInfo.UnderlineThickness; |
| m_FaceInfo.strikethroughOffset = m_fontInfo.strikethrough; |
| m_FaceInfo.strikethroughThickness = m_fontInfo.strikethroughThickness; |
|
|
| m_FaceInfo.tabWidth = m_fontInfo.TabWidth; |
|
|
| if (m_AtlasTextures == null || m_AtlasTextures.Length == 0) |
| m_AtlasTextures = new Texture2D[1]; |
|
|
| m_AtlasTextures[0] = atlas; |
|
|
| |
|
|
| m_AtlasWidth = (int)m_fontInfo.AtlasWidth; |
| m_AtlasHeight = (int)m_fontInfo.AtlasHeight; |
| m_AtlasPadding = (int)m_fontInfo.Padding; |
|
|
| switch(m_CreationSettings.renderMode) |
| { |
| case 0: |
| m_AtlasRenderMode = GlyphRenderMode.SMOOTH_HINTED; |
| break; |
| case 1: |
| m_AtlasRenderMode = GlyphRenderMode.SMOOTH; |
| break; |
| case 2: |
| m_AtlasRenderMode = GlyphRenderMode.RASTER_HINTED; |
| break; |
| case 3: |
| m_AtlasRenderMode = GlyphRenderMode.RASTER; |
| break; |
| case 6: |
| m_AtlasRenderMode = GlyphRenderMode.SDF16; |
| break; |
| case 7: |
| m_AtlasRenderMode = GlyphRenderMode.SDF32; |
| break; |
| } |
|
|
| |
|
|
| |
| if (fontWeights != null && fontWeights.Length > 0) |
| { |
| m_FontWeightTable[4] = fontWeights[4]; |
| m_FontWeightTable[7] = fontWeights[7]; |
|
|
| |
| |
| } |
|
|
| |
| if (fallbackFontAssets != null && fallbackFontAssets.Count > 0) |
| { |
| if (m_FallbackFontAssetTable == null) |
| m_FallbackFontAssetTable = new List<TMP_FontAsset>(fallbackFontAssets.Count); |
|
|
| for (int i = 0; i < fallbackFontAssets.Count; i++) |
| m_FallbackFontAssetTable.Add(fallbackFontAssets[i]); |
|
|
| |
| |
| } |
|
|
| |
| if (m_CreationSettings.sourceFontFileGUID != null || m_CreationSettings.sourceFontFileGUID != string.Empty) |
| { |
| m_SourceFontFileGUID = m_CreationSettings.sourceFontFileGUID; |
| } |
| else |
| { |
| Debug.LogWarning("Font asset [" + this.name + "] doesn't have a reference to its source font file. Please assign the appropriate source font file for this asset in the Font Atlas & Material section of font asset inspector.", this); |
| } |
|
|
| |
| m_GlyphTable.Clear(); |
| m_CharacterTable.Clear(); |
|
|
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
|
|
| bool isSpaceCharacterPresent = false; |
| for (int i = 0; i < m_glyphInfoList.Count; i++) |
| { |
| TMP_Glyph oldGlyph = m_glyphInfoList[i]; |
|
|
| Glyph glyph = new Glyph(); |
|
|
| uint glyphIndex = (uint)i + 1; |
|
|
| |
| |
| |
| |
|
|
| glyph.index = glyphIndex; |
| glyph.glyphRect = new GlyphRect((int)oldGlyph.x, m_AtlasHeight - (int)(oldGlyph.y + oldGlyph.height + 0.5f), (int)(oldGlyph.width + 0.5f), (int)(oldGlyph.height + 0.5f)); |
| glyph.metrics = new GlyphMetrics(oldGlyph.width, oldGlyph.height, oldGlyph.xOffset, oldGlyph.yOffset, oldGlyph.xAdvance); |
| glyph.scale = oldGlyph.scale; |
| glyph.atlasIndex = 0; |
|
|
| m_GlyphTable.Add(glyph); |
|
|
| TMP_Character character = new TMP_Character((uint)oldGlyph.id, this, glyph); |
|
|
| if (oldGlyph.id == 32) |
| isSpaceCharacterPresent = true; |
|
|
| m_CharacterTable.Add(character); |
| } |
|
|
| |
| if (!isSpaceCharacterPresent) |
| { |
| Debug.Log("Synthesizing Space for [" + this.name + "]"); |
| Glyph glyph = new Glyph(0, new GlyphMetrics(0, 0, 0, 0, m_FaceInfo.ascentLine / 5), GlyphRect.zero, 1.0f, 0); |
| m_GlyphTable.Add(glyph); |
| m_CharacterTable.Add(new TMP_Character(32, this, glyph)); |
| } |
|
|
| |
| |
|
|
| ReadFontAssetDefinition(); |
|
|
| |
| |
| #if UNITY_EDITOR |
| if (UnityEditor.EditorUtility.IsPersistent(this)) |
| { |
| TMP_EditorResourceManager.RegisterResourceForUpdate(this); |
| } |
| #endif |
| } |
|
|
| |
| |
| |
| void UpgradeGlyphAdjustmentTableToFontFeatureTable() |
| { |
| Debug.Log("Upgrading font asset [" + this.name + "] Glyph Adjustment Table.", this); |
|
|
| if (m_FontFeatureTable == null) |
| m_FontFeatureTable = new TMP_FontFeatureTable(); |
|
|
| int pairCount = m_KerningTable.kerningPairs.Count; |
|
|
| m_FontFeatureTable.m_GlyphPairAdjustmentRecords = new List<TMP_GlyphPairAdjustmentRecord>(pairCount); |
|
|
| for (int i = 0; i < pairCount; i++) |
| { |
| KerningPair pair = m_KerningTable.kerningPairs[i]; |
|
|
| uint firstGlyphIndex = 0; |
| TMP_Character firstCharacter; |
|
|
| if (m_CharacterLookupDictionary.TryGetValue(pair.firstGlyph, out firstCharacter)) |
| firstGlyphIndex = firstCharacter.glyphIndex; |
|
|
| uint secondGlyphIndex = 0; |
| TMP_Character secondCharacter; |
|
|
| if (m_CharacterLookupDictionary.TryGetValue(pair.secondGlyph, out secondCharacter)) |
| secondGlyphIndex = secondCharacter.glyphIndex; |
|
|
| TMP_GlyphAdjustmentRecord firstAdjustmentRecord = new TMP_GlyphAdjustmentRecord(firstGlyphIndex, new TMP_GlyphValueRecord(pair.firstGlyphAdjustments.xPlacement, pair.firstGlyphAdjustments.yPlacement, pair.firstGlyphAdjustments.xAdvance, pair.firstGlyphAdjustments.yAdvance)); |
| TMP_GlyphAdjustmentRecord secondAdjustmentRecord = new TMP_GlyphAdjustmentRecord(secondGlyphIndex, new TMP_GlyphValueRecord(pair.secondGlyphAdjustments.xPlacement, pair.secondGlyphAdjustments.yPlacement, pair.secondGlyphAdjustments.xAdvance, pair.secondGlyphAdjustments.yAdvance)); |
| TMP_GlyphPairAdjustmentRecord record = new TMP_GlyphPairAdjustmentRecord(firstAdjustmentRecord, secondAdjustmentRecord); |
|
|
| m_FontFeatureTable.m_GlyphPairAdjustmentRecords.Add(record); |
| } |
|
|
| |
| m_KerningTable.kerningPairs = null; |
| m_KerningTable = null; |
|
|
| #if UNITY_EDITOR |
| if (UnityEditor.EditorUtility.IsPersistent(this)) |
| { |
| TMP_EditorResourceManager.RegisterResourceForUpdate(this); |
| } |
| #endif |
| } |
|
|
| } |
| } |
|
|