189 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			189 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|  | using System.Collections.Generic; | ||
|  | using UnityEngine; | ||
|  | using UnityEngine.TextCore.LowLevel; | ||
|  | 
 | ||
|  | 
 | ||
|  | namespace TMPro | ||
|  | { | ||
|  |     internal class TMP_DynamicFontAssetUtilities | ||
|  |     { | ||
|  |         private static TMP_DynamicFontAssetUtilities s_Instance = new TMP_DynamicFontAssetUtilities(); | ||
|  | 
 | ||
|  |         private Dictionary<ulong, FontReference> s_SystemFontLookup; | ||
|  |         private string[] s_SystemFontPaths; | ||
|  |         private uint s_RegularStyleNameHashCode = 1291372090; | ||
|  | 
 | ||
|  |         public struct FontReference | ||
|  |         { | ||
|  |             public string familyName; | ||
|  |             public string styleName; | ||
|  |             public int faceIndex; | ||
|  |             public string filePath; | ||
|  |             public ulong hashCode; | ||
|  | 
 | ||
|  |             /// <summary> | ||
|  |             /// Constructor for new FontReference | ||
|  |             /// </summary> | ||
|  |             /// <param name="faceNameAndStyle">String that combines the family name with style name</param> | ||
|  |             /// <param name="index">Index of the font face and style.</param> | ||
|  |             public FontReference(string fontFilePath, string faceNameAndStyle, int index) | ||
|  |             { | ||
|  |                 familyName = null; | ||
|  |                 styleName = null; | ||
|  |                 faceIndex = index; | ||
|  |                 uint familyNameHashCode = 0; | ||
|  |                 uint styleNameHashCode = 0; | ||
|  |                 filePath = fontFilePath; | ||
|  | 
 | ||
|  |                 int length = faceNameAndStyle.Length; | ||
|  |                 char[] conversionArray = new char[length]; | ||
|  | 
 | ||
|  |                 int readingFlag = 0; | ||
|  |                 int writingIndex = 0; | ||
|  | 
 | ||
|  |                 for (int i = 0; i < length; i++) | ||
|  |                 { | ||
|  |                     char c = faceNameAndStyle[i]; | ||
|  | 
 | ||
|  |                     // Read family name | ||
|  |                     if (readingFlag == 0) | ||
|  |                     { | ||
|  |                         bool isSeparator = i + 2 < length && c == ' ' && faceNameAndStyle[i + 1] == '-' && faceNameAndStyle[i + 2] == ' '; | ||
|  | 
 | ||
|  |                         if (isSeparator) | ||
|  |                         { | ||
|  |                             readingFlag = 1; | ||
|  |                             this.familyName = new string(conversionArray, 0, writingIndex); | ||
|  |                             i += 2; | ||
|  |                             writingIndex = 0; | ||
|  |                             continue; | ||
|  |                         } | ||
|  | 
 | ||
|  |                         familyNameHashCode = (familyNameHashCode << 5) + familyNameHashCode ^ TMP_TextUtilities.ToUpperFast(c); | ||
|  |                         conversionArray[writingIndex++] = c; | ||
|  |                         continue; | ||
|  |                     } | ||
|  | 
 | ||
|  |                     // Read style name | ||
|  |                     if (readingFlag == 1) | ||
|  |                     { | ||
|  |                         styleNameHashCode = (styleNameHashCode << 5) + styleNameHashCode ^ TMP_TextUtilities.ToUpperFast(c); | ||
|  |                         conversionArray[writingIndex++] = c; | ||
|  | 
 | ||
|  |                         if (i + 1 == length) | ||
|  |                             this.styleName = new string(conversionArray, 0, writingIndex); | ||
|  |                     } | ||
|  |                 } | ||
|  | 
 | ||
|  |                 hashCode = (ulong)styleNameHashCode << 32 | familyNameHashCode; | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  | 
 | ||
|  |         void InitializeSystemFontReferenceCache() | ||
|  |         { | ||
|  |             if (s_SystemFontLookup == null) | ||
|  |                 s_SystemFontLookup = new Dictionary<ulong, FontReference>(); | ||
|  |             else | ||
|  |                 s_SystemFontLookup.Clear(); | ||
|  | 
 | ||
|  |             if (s_SystemFontPaths == null) | ||
|  |                 s_SystemFontPaths = Font.GetPathsToOSFonts(); | ||
|  | 
 | ||
|  |             for (int i = 0; i < s_SystemFontPaths.Length; i++) | ||
|  |             { | ||
|  |                 // Load font at the given path | ||
|  |                 FontEngineError error = FontEngine.LoadFontFace(s_SystemFontPaths[i]); | ||
|  |                 if (error != FontEngineError.Success) | ||
|  |                 { | ||
|  |                     Debug.LogWarning("Error [" + error + "] trying to load the font at path [" + s_SystemFontPaths[i] + "]."); | ||
|  |                     continue; | ||
|  |                 } | ||
|  | 
 | ||
|  |                 // Get font faces and styles for this font | ||
|  |                 string[] fontFaces = FontEngine.GetFontFaces(); | ||
|  | 
 | ||
|  |                 // Iterate over each font face | ||
|  |                 for (int j = 0; j < fontFaces.Length; j++) | ||
|  |                 { | ||
|  |                     FontReference fontRef = new FontReference(s_SystemFontPaths[i], fontFaces[j], j); | ||
|  | 
 | ||
|  |                     if (s_SystemFontLookup.ContainsKey(fontRef.hashCode)) | ||
|  |                     { | ||
|  |                         //Debug.Log("<color=#FFFF80>[" + i + "]</color> Family Name <color=#FFFF80>[" + fontRef.familyName + "]</color>   Style Name <color=#FFFF80>[" + fontRef.styleName + "]</color>   Index [" + fontRef.faceIndex + "]   HashCode [" + fontRef.hashCode + "]    Path [" + fontRef.filePath + "]."); | ||
|  |                         continue; | ||
|  |                     } | ||
|  | 
 | ||
|  |                     // Add font reference to lookup dictionary | ||
|  |                     s_SystemFontLookup.Add(fontRef.hashCode, fontRef); | ||
|  | 
 | ||
|  |                     Debug.Log("[" + i + "] Family Name [" + fontRef.familyName + "]   Style Name [" + fontRef.styleName + "]   Index [" + fontRef.faceIndex + "]   HashCode [" + fontRef.hashCode + "]    Path [" + fontRef.filePath + "]."); | ||
|  |                 } | ||
|  | 
 | ||
|  |                 // Unload current font face. | ||
|  |                 FontEngine.UnloadFontFace(); | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  | 
 | ||
|  |         /// <summary> | ||
|  |         /// | ||
|  |         /// </summary> | ||
|  |         /// <param name="familyName"></param> | ||
|  |         /// <param name="fontRef"></param> | ||
|  |         /// <returns></returns> | ||
|  |         public static bool TryGetSystemFontReference(string familyName, out FontReference fontRef) | ||
|  |         { | ||
|  |             return s_Instance.TryGetSystemFontReferenceInternal(familyName, null, out fontRef); | ||
|  |         } | ||
|  | 
 | ||
|  |         /// <summary> | ||
|  |         /// | ||
|  |         /// </summary> | ||
|  |         /// <param name="familyName"></param> | ||
|  |         /// <param name="styleName"></param> | ||
|  |         /// <param name="fontRef"></param> | ||
|  |         /// <returns></returns> | ||
|  |         public static bool TryGetSystemFontReference(string familyName, string styleName, out FontReference fontRef) | ||
|  |         { | ||
|  |             return s_Instance.TryGetSystemFontReferenceInternal(familyName, styleName, out fontRef); | ||
|  |         } | ||
|  | 
 | ||
|  |         bool TryGetSystemFontReferenceInternal(string familyName, string styleName, out FontReference fontRef) | ||
|  |         { | ||
|  |             if (s_SystemFontLookup == null) | ||
|  |                 InitializeSystemFontReferenceCache(); | ||
|  | 
 | ||
|  |             fontRef = new FontReference(); | ||
|  | 
 | ||
|  |             // Compute family name hash code | ||
|  |             uint familyNameHashCode = TMP_TextUtilities.GetHashCodeCaseInSensitive(familyName); | ||
|  |             uint styleNameHashCode = string.IsNullOrEmpty(styleName) ? s_RegularStyleNameHashCode : TMP_TextUtilities.GetHashCodeCaseInSensitive(styleName); | ||
|  |             ulong key = (ulong)styleNameHashCode << 32 | familyNameHashCode; | ||
|  | 
 | ||
|  |             // Lookup font reference | ||
|  |             if (s_SystemFontLookup.ContainsKey(key)) | ||
|  |             { | ||
|  |                 fontRef = s_SystemFontLookup[key]; | ||
|  |                 return true; | ||
|  |             } | ||
|  | 
 | ||
|  |             // Return if specified family and style name is not found. | ||
|  |             if (styleNameHashCode != s_RegularStyleNameHashCode) | ||
|  |                 return false; | ||
|  | 
 | ||
|  |             // Return first potential reference for the given family name | ||
|  |             foreach (KeyValuePair<ulong, FontReference> pair in s_SystemFontLookup) | ||
|  |             { | ||
|  |                 if (pair.Value.familyName == familyName) | ||
|  |                 { | ||
|  |                     fontRef = pair.Value; | ||
|  |                     return true; | ||
|  |                 } | ||
|  |             } | ||
|  | 
 | ||
|  |             return false; | ||
|  |         } | ||
|  |     } | ||
|  | } |