466 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			466 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|  | using UnityEngine; | |||
|  | using UnityEngine.Serialization; | |||
|  | using UnityEngine.TextCore; | |||
|  | using UnityEngine.TextCore.LowLevel; | |||
|  | using System; | |||
|  | using System.Collections; | |||
|  | using System.Collections.Generic; | |||
|  | using System.Linq; | |||
|  | 
 | |||
|  | 
 | |||
|  | namespace TMPro | |||
|  | { | |||
|  |     /// <summary> | |||
|  |     /// Class that contains the basic information about the font. | |||
|  |     /// </summary> | |||
|  |     [Serializable] | |||
|  |     public class FaceInfo_Legacy | |||
|  |     { | |||
|  |         public string Name; | |||
|  |         public float PointSize; | |||
|  |         public float Scale; | |||
|  | 
 | |||
|  |         public int CharacterCount; | |||
|  | 
 | |||
|  |         public float LineHeight; | |||
|  |         public float Baseline; | |||
|  |         public float Ascender; | |||
|  |         public float CapHeight; | |||
|  |         public float Descender; | |||
|  |         public float CenterLine; | |||
|  | 
 | |||
|  |         public float SuperscriptOffset; | |||
|  |         public float SubscriptOffset; | |||
|  |         public float SubSize; | |||
|  | 
 | |||
|  |         public float Underline; | |||
|  |         public float UnderlineThickness; | |||
|  | 
 | |||
|  |         public float strikethrough; | |||
|  |         public float strikethroughThickness; | |||
|  | 
 | |||
|  |         public float TabWidth; | |||
|  | 
 | |||
|  |         public float Padding; | |||
|  |         public float AtlasWidth; | |||
|  |         public float AtlasHeight; | |||
|  |     } | |||
|  | 
 | |||
|  | 
 | |||
|  |     // Class which contains the Glyph Info / Character definition for each character contained in the font asset. | |||
|  |     [Serializable] | |||
|  |     public class TMP_Glyph : TMP_TextElement_Legacy | |||
|  |     { | |||
|  |         /// <summary> | |||
|  |         /// Function to create a deep copy of a GlyphInfo. | |||
|  |         /// </summary> | |||
|  |         /// <param name="source"></param> | |||
|  |         /// <returns></returns> | |||
|  |         public static TMP_Glyph Clone(TMP_Glyph source) | |||
|  |         { | |||
|  |             TMP_Glyph copy = new TMP_Glyph(); | |||
|  | 
 | |||
|  |             copy.id = source.id; | |||
|  |             copy.x = source.x; | |||
|  |             copy.y = source.y; | |||
|  |             copy.width = source.width; | |||
|  |             copy.height = source.height; | |||
|  |             copy.xOffset = source.xOffset; | |||
|  |             copy.yOffset = source.yOffset; | |||
|  |             copy.xAdvance = source.xAdvance; | |||
|  |             copy.scale = source.scale; | |||
|  | 
 | |||
|  |             return copy; | |||
|  |         } | |||
|  |     } | |||
|  | 
 | |||
|  | 
 | |||
|  |     // Structure which holds the font creation settings | |||
|  |     [Serializable] | |||
|  |     public struct FontAssetCreationSettings | |||
|  |     { | |||
|  |         public string sourceFontFileName; | |||
|  |         public string sourceFontFileGUID; | |||
|  |         public int faceIndex; | |||
|  |         public int pointSizeSamplingMode; | |||
|  |         public int pointSize; | |||
|  |         public int padding; | |||
|  |         public int paddingMode; | |||
|  |         public int packingMode; | |||
|  |         public int atlasWidth; | |||
|  |         public int atlasHeight; | |||
|  |         public int characterSetSelectionMode; | |||
|  |         public string characterSequence; | |||
|  |         public string referencedFontAssetGUID; | |||
|  |         public string referencedTextAssetGUID; | |||
|  |         public int fontStyle; | |||
|  |         public float fontStyleModifier; | |||
|  |         public int renderMode; | |||
|  |         public bool includeFontFeatures; | |||
|  | 
 | |||
|  |         internal FontAssetCreationSettings(string sourceFontFileGUID, int pointSize, int pointSizeSamplingMode, int padding, int packingMode, int atlasWidth, int atlasHeight, int characterSelectionMode, string characterSet, int renderMode) | |||
|  |         { | |||
|  |             this.sourceFontFileName = string.Empty; | |||
|  |             this.sourceFontFileGUID = sourceFontFileGUID; | |||
|  |             this.faceIndex = 0; | |||
|  |             this.pointSize = pointSize; | |||
|  |             this.pointSizeSamplingMode = pointSizeSamplingMode; | |||
|  |             this.padding = padding; | |||
|  |             this.paddingMode = 2; | |||
|  |             this.packingMode = packingMode; | |||
|  |             this.atlasWidth = atlasWidth; | |||
|  |             this.atlasHeight = atlasHeight; | |||
|  |             this.characterSequence = characterSet; | |||
|  |             this.characterSetSelectionMode = characterSelectionMode; | |||
|  |             this.renderMode = renderMode; | |||
|  | 
 | |||
|  |             this.referencedFontAssetGUID = string.Empty; | |||
|  |             this.referencedTextAssetGUID = string.Empty; | |||
|  |             this.fontStyle = 0; | |||
|  |             this.fontStyleModifier = 0; | |||
|  |             this.includeFontFeatures = false; | |||
|  |         } | |||
|  |     } | |||
|  | 
 | |||
|  |     /// <summary> | |||
|  |     /// Contains the font assets for the regular and italic styles associated with a given font weight. | |||
|  |     /// </summary> | |||
|  |     [Serializable] | |||
|  |     public struct TMP_FontWeightPair | |||
|  |     { | |||
|  |         public TMP_FontAsset regularTypeface; | |||
|  |         public TMP_FontAsset italicTypeface; | |||
|  |     } | |||
|  | 
 | |||
|  | 
 | |||
|  |     public struct KerningPairKey | |||
|  |     { | |||
|  |         public uint ascii_Left; | |||
|  |         public uint ascii_Right; | |||
|  |         public uint key; | |||
|  | 
 | |||
|  |         public KerningPairKey(uint ascii_left, uint ascii_right) | |||
|  |         { | |||
|  |             ascii_Left = ascii_left; | |||
|  |             ascii_Right = ascii_right; | |||
|  |             key = (ascii_right << 16) + ascii_left; | |||
|  |         } | |||
|  |     } | |||
|  | 
 | |||
|  |     /// <summary> | |||
|  |     /// Positional adjustments of a glyph | |||
|  |     /// </summary> | |||
|  |     [Serializable] | |||
|  |     public struct GlyphValueRecord_Legacy | |||
|  |     { | |||
|  |         public float xPlacement; | |||
|  |         public float yPlacement; | |||
|  |         public float xAdvance; | |||
|  |         public float yAdvance; | |||
|  | 
 | |||
|  |         internal GlyphValueRecord_Legacy(UnityEngine.TextCore.LowLevel.GlyphValueRecord valueRecord) | |||
|  |         { | |||
|  |             this.xPlacement = valueRecord.xPlacement; | |||
|  |             this.yPlacement = valueRecord.yPlacement; | |||
|  |             this.xAdvance = valueRecord.xAdvance; | |||
|  |             this.yAdvance = valueRecord.yAdvance; | |||
|  |         } | |||
|  | 
 | |||
|  |         public static GlyphValueRecord_Legacy operator +(GlyphValueRecord_Legacy a, GlyphValueRecord_Legacy b) | |||
|  |         { | |||
|  |             GlyphValueRecord_Legacy c; | |||
|  |             c.xPlacement = a.xPlacement + b.xPlacement; | |||
|  |             c.yPlacement = a.yPlacement + b.yPlacement; | |||
|  |             c.xAdvance = a.xAdvance + b.xAdvance; | |||
|  |             c.yAdvance = a.yAdvance + b.yAdvance; | |||
|  | 
 | |||
|  |             return c; | |||
|  |         } | |||
|  |     } | |||
|  | 
 | |||
|  |     [Serializable] | |||
|  |     public class KerningPair | |||
|  |     { | |||
|  |         /// <summary> | |||
|  |         /// The first glyph part of a kerning pair. | |||
|  |         /// </summary> | |||
|  |         public uint firstGlyph | |||
|  |         { | |||
|  |             get { return m_FirstGlyph; } | |||
|  |             set { m_FirstGlyph = value; } | |||
|  |         } | |||
|  |         [FormerlySerializedAs("AscII_Left")] | |||
|  |         [SerializeField] | |||
|  |         private uint m_FirstGlyph; | |||
|  | 
 | |||
|  |         /// <summary> | |||
|  |         /// The positional adjustment of the first glyph. | |||
|  |         /// </summary> | |||
|  |         public GlyphValueRecord_Legacy firstGlyphAdjustments | |||
|  |         { | |||
|  |             get { return m_FirstGlyphAdjustments; } | |||
|  |         } | |||
|  |         [SerializeField] | |||
|  |         private GlyphValueRecord_Legacy m_FirstGlyphAdjustments; | |||
|  | 
 | |||
|  |         /// <summary> | |||
|  |         /// The second glyph part of a kerning pair. | |||
|  |         /// </summary> | |||
|  |         public uint secondGlyph | |||
|  |         { | |||
|  |             get { return m_SecondGlyph; } | |||
|  |             set { m_SecondGlyph = value; } | |||
|  |         } | |||
|  |         [FormerlySerializedAs("AscII_Right")] | |||
|  |         [SerializeField] | |||
|  |         private uint m_SecondGlyph; | |||
|  | 
 | |||
|  |         /// <summary> | |||
|  |         /// The positional adjustment of the second glyph. | |||
|  |         /// </summary> | |||
|  |         public GlyphValueRecord_Legacy secondGlyphAdjustments | |||
|  |         { | |||
|  |             get { return m_SecondGlyphAdjustments; } | |||
|  |         } | |||
|  |         [SerializeField] | |||
|  |         private GlyphValueRecord_Legacy m_SecondGlyphAdjustments; | |||
|  | 
 | |||
|  |         [FormerlySerializedAs("XadvanceOffset")] | |||
|  |         public float xOffset; | |||
|  | 
 | |||
|  |         internal static KerningPair empty = new KerningPair(0, new GlyphValueRecord_Legacy(), 0, new GlyphValueRecord_Legacy()); | |||
|  | 
 | |||
|  |         /// <summary> | |||
|  |         /// Determines if the Character Spacing property of the text object will affect the kerning pair. | |||
|  |         /// This is mostly relevant when using Diacritical marks to prevent Character Spacing from altering the spacing. | |||
|  |         /// </summary> | |||
|  |         public bool ignoreSpacingAdjustments | |||
|  |         { | |||
|  |             get { return m_IgnoreSpacingAdjustments; } | |||
|  |         } | |||
|  |         [SerializeField] | |||
|  |         private bool m_IgnoreSpacingAdjustments = false; | |||
|  | 
 | |||
|  |         public KerningPair() | |||
|  |         { | |||
|  |             m_FirstGlyph = 0; | |||
|  |             m_FirstGlyphAdjustments = new GlyphValueRecord_Legacy(); | |||
|  | 
 | |||
|  |             m_SecondGlyph = 0; | |||
|  |             m_SecondGlyphAdjustments = new GlyphValueRecord_Legacy(); | |||
|  |         } | |||
|  | 
 | |||
|  |         public KerningPair(uint left, uint right, float offset) | |||
|  |         { | |||
|  |             firstGlyph = left; | |||
|  |             m_SecondGlyph = right; | |||
|  |             xOffset = offset; | |||
|  |         } | |||
|  | 
 | |||
|  |         public KerningPair(uint firstGlyph, GlyphValueRecord_Legacy firstGlyphAdjustments, uint secondGlyph, GlyphValueRecord_Legacy secondGlyphAdjustments) | |||
|  |         { | |||
|  |             m_FirstGlyph = firstGlyph; | |||
|  |             m_FirstGlyphAdjustments = firstGlyphAdjustments; | |||
|  |             m_SecondGlyph = secondGlyph; | |||
|  |             m_SecondGlyphAdjustments = secondGlyphAdjustments; | |||
|  |         } | |||
|  | 
 | |||
|  |         internal void ConvertLegacyKerningData() | |||
|  |         { | |||
|  |             m_FirstGlyphAdjustments.xAdvance = xOffset; | |||
|  |             //xOffset = 0; | |||
|  |         } | |||
|  | 
 | |||
|  |     } | |||
|  | 
 | |||
|  |     [Serializable] | |||
|  |     public class KerningTable | |||
|  |     { | |||
|  |         public List<KerningPair> kerningPairs; | |||
|  | 
 | |||
|  |         public KerningTable() | |||
|  |         { | |||
|  |             kerningPairs = new List<KerningPair>(); | |||
|  |         } | |||
|  | 
 | |||
|  | 
 | |||
|  |         public void AddKerningPair() | |||
|  |         { | |||
|  |             if (kerningPairs.Count == 0) | |||
|  |             { | |||
|  |                 kerningPairs.Add(new KerningPair(0, 0, 0)); | |||
|  |             } | |||
|  |             else | |||
|  |             { | |||
|  |                 uint left = kerningPairs.Last().firstGlyph; | |||
|  |                 uint right = kerningPairs.Last().secondGlyph; | |||
|  |                 float xoffset = kerningPairs.Last().xOffset; | |||
|  | 
 | |||
|  |                 kerningPairs.Add(new KerningPair(left, right, xoffset)); | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  | 
 | |||
|  |         /// <summary> | |||
|  |         /// Add Kerning Pair | |||
|  |         /// </summary> | |||
|  |         /// <param name="first">First glyph</param> | |||
|  |         /// <param name="second">Second glyph</param> | |||
|  |         /// <param name="offset">xAdvance value</param> | |||
|  |         /// <returns></returns> | |||
|  |         public int AddKerningPair(uint first, uint second, float offset) | |||
|  |         { | |||
|  |             int index = kerningPairs.FindIndex(item => item.firstGlyph == first && item.secondGlyph == second); | |||
|  | 
 | |||
|  |             if (index == -1) | |||
|  |             { | |||
|  |                 kerningPairs.Add(new KerningPair(first, second, offset)); | |||
|  |                 return 0; | |||
|  |             } | |||
|  | 
 | |||
|  |             // Return -1 if Kerning Pair already exists. | |||
|  |             return -1; | |||
|  |         } | |||
|  | 
 | |||
|  |         /// <summary> | |||
|  |         /// Add Glyph pair adjustment record | |||
|  |         /// </summary> | |||
|  |         /// <param name="firstGlyph">The first glyph</param> | |||
|  |         /// <param name="firstGlyphAdjustments">Adjustment record for the first glyph</param> | |||
|  |         /// <param name="secondGlyph">The second glyph</param> | |||
|  |         /// <param name="secondGlyphAdjustments">Adjustment record for the second glyph</param> | |||
|  |         /// <returns></returns> | |||
|  |         public int AddGlyphPairAdjustmentRecord(uint first, GlyphValueRecord_Legacy firstAdjustments, uint second, GlyphValueRecord_Legacy secondAdjustments) | |||
|  |         { | |||
|  |             int index = kerningPairs.FindIndex(item => item.firstGlyph == first && item.secondGlyph == second); | |||
|  | 
 | |||
|  |             if (index == -1) | |||
|  |             { | |||
|  |                 kerningPairs.Add(new KerningPair(first, firstAdjustments, second, secondAdjustments)); | |||
|  |                 return 0; | |||
|  |             } | |||
|  | 
 | |||
|  |             // Return -1 if Kerning Pair already exists. | |||
|  |             return -1; | |||
|  |         } | |||
|  | 
 | |||
|  |         public void RemoveKerningPair(int left, int right) | |||
|  |         { | |||
|  |             int index = kerningPairs.FindIndex(item => item.firstGlyph == left && item.secondGlyph == right); | |||
|  | 
 | |||
|  |             if (index != -1) | |||
|  |                 kerningPairs.RemoveAt(index); | |||
|  |         } | |||
|  | 
 | |||
|  | 
 | |||
|  |         public void RemoveKerningPair(int index) | |||
|  |         { | |||
|  |             kerningPairs.RemoveAt(index); | |||
|  |         } | |||
|  | 
 | |||
|  | 
 | |||
|  |         public void SortKerningPairs() | |||
|  |         { | |||
|  |             // Sort List of Kerning Info | |||
|  |             if (kerningPairs.Count > 0) | |||
|  |                 kerningPairs = kerningPairs.OrderBy(s => s.firstGlyph).ThenBy(s => s.secondGlyph).ToList(); | |||
|  |         } | |||
|  |     } | |||
|  | 
 | |||
|  | 
 | |||
|  |     public static class TMP_FontUtilities | |||
|  |     { | |||
|  |         private static List<int> k_searchedFontAssets; | |||
|  | 
 | |||
|  |         /// <summary> | |||
|  |         /// Search through the given font and its fallbacks for the specified character. | |||
|  |         /// </summary> | |||
|  |         /// <param name="font">The font asset to search for the given character.</param> | |||
|  |         /// <param name="unicode">The character to find.</param> | |||
|  |         /// <param name="character">out parameter containing the glyph for the specified character (if found).</param> | |||
|  |         /// <returns></returns> | |||
|  |         public static TMP_FontAsset SearchForCharacter(TMP_FontAsset font, uint unicode, out TMP_Character character) | |||
|  |         { | |||
|  |             if (k_searchedFontAssets == null) | |||
|  |                 k_searchedFontAssets = new List<int>(); | |||
|  | 
 | |||
|  |             k_searchedFontAssets.Clear(); | |||
|  | 
 | |||
|  |             return SearchForCharacterInternal(font, unicode, out character); | |||
|  |         } | |||
|  | 
 | |||
|  | 
 | |||
|  |         /// <summary> | |||
|  |         /// Search through the given list of fonts and their possible fallbacks for the specified character. | |||
|  |         /// </summary> | |||
|  |         /// <param name="fonts"></param> | |||
|  |         /// <param name="unicode"></param> | |||
|  |         /// <param name="character"></param> | |||
|  |         /// <returns></returns> | |||
|  |         public static TMP_FontAsset SearchForCharacter(List<TMP_FontAsset> fonts, uint unicode, out TMP_Character character) | |||
|  |         { | |||
|  |             return SearchForCharacterInternal(fonts, unicode, out character); | |||
|  |         } | |||
|  | 
 | |||
|  | 
 | |||
|  |         private static TMP_FontAsset SearchForCharacterInternal(TMP_FontAsset font, uint unicode, out TMP_Character character) | |||
|  |         { | |||
|  |             character = null; | |||
|  | 
 | |||
|  |             if (font == null) return null; | |||
|  | 
 | |||
|  |             if (font.characterLookupTable.TryGetValue(unicode, out character)) | |||
|  |             { | |||
|  |                 if (character.textAsset != null) | |||
|  |                     return font; | |||
|  | 
 | |||
|  |                 // Remove character from lookup table | |||
|  |                 font.characterLookupTable.Remove(unicode); | |||
|  |             } | |||
|  | 
 | |||
|  |             if (font.fallbackFontAssetTable != null && font.fallbackFontAssetTable.Count > 0) | |||
|  |             { | |||
|  |                 for (int i = 0; i < font.fallbackFontAssetTable.Count && character == null; i++) | |||
|  |                 { | |||
|  |                     TMP_FontAsset temp = font.fallbackFontAssetTable[i]; | |||
|  |                     if (temp == null) continue; | |||
|  | 
 | |||
|  |                     int id = temp.GetInstanceID(); | |||
|  | 
 | |||
|  |                     // Skip over the fallback font asset in the event it is null or if already searched. | |||
|  |                     if (k_searchedFontAssets.Contains(id)) continue; | |||
|  | 
 | |||
|  |                     // Add to list of font assets already searched. | |||
|  |                     k_searchedFontAssets.Add(id); | |||
|  | 
 | |||
|  |                     temp = SearchForCharacterInternal(temp, unicode, out character); | |||
|  | 
 | |||
|  |                     if (temp != null) | |||
|  |                         return temp; | |||
|  |                 } | |||
|  |             } | |||
|  | 
 | |||
|  |             return null; | |||
|  |         } | |||
|  | 
 | |||
|  | 
 | |||
|  |         private static TMP_FontAsset SearchForCharacterInternal(List<TMP_FontAsset> fonts, uint unicode, out TMP_Character character) | |||
|  |         { | |||
|  |             character = null; | |||
|  | 
 | |||
|  |             if (fonts != null && fonts.Count > 0) | |||
|  |             { | |||
|  |                 for (int i = 0; i < fonts.Count; i++) | |||
|  |                 { | |||
|  |                     TMP_FontAsset fontAsset = SearchForCharacterInternal(fonts[i], unicode, out character); | |||
|  | 
 | |||
|  |                     if (fontAsset != null) | |||
|  |                         return fontAsset; | |||
|  |                 } | |||
|  |             } | |||
|  | 
 | |||
|  |             return null; | |||
|  |         } | |||
|  |     } | |||
|  | } |