TMP_FontAssetCommon.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. using UnityEngine;
  2. using UnityEngine.Serialization;
  3. using UnityEngine.TextCore;
  4. using UnityEngine.TextCore.LowLevel;
  5. using System;
  6. using System.Collections;
  7. using System.Collections.Generic;
  8. using System.Linq;
  9. namespace TMPro
  10. {
  11. /// <summary>
  12. /// Class that contains the basic information about the font.
  13. /// </summary>
  14. [Serializable]
  15. public class FaceInfo_Legacy
  16. {
  17. public string Name;
  18. public float PointSize;
  19. public float Scale;
  20. public int CharacterCount;
  21. public float LineHeight;
  22. public float Baseline;
  23. public float Ascender;
  24. public float CapHeight;
  25. public float Descender;
  26. public float CenterLine;
  27. public float SuperscriptOffset;
  28. public float SubscriptOffset;
  29. public float SubSize;
  30. public float Underline;
  31. public float UnderlineThickness;
  32. public float strikethrough;
  33. public float strikethroughThickness;
  34. public float TabWidth;
  35. public float Padding;
  36. public float AtlasWidth;
  37. public float AtlasHeight;
  38. }
  39. // Class which contains the Glyph Info / Character definition for each character contained in the font asset.
  40. [Serializable]
  41. public class TMP_Glyph : TMP_TextElement_Legacy
  42. {
  43. /// <summary>
  44. /// Function to create a deep copy of a GlyphInfo.
  45. /// </summary>
  46. /// <param name="source"></param>
  47. /// <returns></returns>
  48. public static TMP_Glyph Clone(TMP_Glyph source)
  49. {
  50. TMP_Glyph copy = new TMP_Glyph();
  51. copy.id = source.id;
  52. copy.x = source.x;
  53. copy.y = source.y;
  54. copy.width = source.width;
  55. copy.height = source.height;
  56. copy.xOffset = source.xOffset;
  57. copy.yOffset = source.yOffset;
  58. copy.xAdvance = source.xAdvance;
  59. copy.scale = source.scale;
  60. return copy;
  61. }
  62. }
  63. // Structure which holds the font creation settings
  64. [Serializable]
  65. public struct FontAssetCreationSettings
  66. {
  67. public string sourceFontFileName;
  68. public string sourceFontFileGUID;
  69. public int pointSizeSamplingMode;
  70. public int pointSize;
  71. public int padding;
  72. public int packingMode;
  73. public int atlasWidth;
  74. public int atlasHeight;
  75. public int characterSetSelectionMode;
  76. public string characterSequence;
  77. public string referencedFontAssetGUID;
  78. public string referencedTextAssetGUID;
  79. public int fontStyle;
  80. public float fontStyleModifier;
  81. public int renderMode;
  82. public bool includeFontFeatures;
  83. internal FontAssetCreationSettings(string sourceFontFileGUID, int pointSize, int pointSizeSamplingMode, int padding, int packingMode, int atlasWidth, int atlasHeight, int characterSelectionMode, string characterSet, int renderMode)
  84. {
  85. this.sourceFontFileName = string.Empty;
  86. this.sourceFontFileGUID = sourceFontFileGUID;
  87. this.pointSize = pointSize;
  88. this.pointSizeSamplingMode = pointSizeSamplingMode;
  89. this.padding = padding;
  90. this.packingMode = packingMode;
  91. this.atlasWidth = atlasWidth;
  92. this.atlasHeight = atlasHeight;
  93. this.characterSequence = characterSet;
  94. this.characterSetSelectionMode = characterSelectionMode;
  95. this.renderMode = renderMode;
  96. this.referencedFontAssetGUID = string.Empty;
  97. this.referencedTextAssetGUID = string.Empty;
  98. this.fontStyle = 0;
  99. this.fontStyleModifier = 0;
  100. this.includeFontFeatures = false;
  101. }
  102. }
  103. /// <summary>
  104. /// Contains the font assets for the regular and italic styles associated with a given font weight.
  105. /// </summary>
  106. [Serializable]
  107. public struct TMP_FontWeightPair
  108. {
  109. public TMP_FontAsset regularTypeface;
  110. public TMP_FontAsset italicTypeface;
  111. }
  112. public struct KerningPairKey
  113. {
  114. public uint ascii_Left;
  115. public uint ascii_Right;
  116. public uint key;
  117. public KerningPairKey(uint ascii_left, uint ascii_right)
  118. {
  119. ascii_Left = ascii_left;
  120. ascii_Right = ascii_right;
  121. key = (ascii_right << 16) + ascii_left;
  122. }
  123. }
  124. /// <summary>
  125. /// Positional adjustments of a glyph
  126. /// </summary>
  127. [Serializable]
  128. public struct GlyphValueRecord_Legacy
  129. {
  130. public float xPlacement;
  131. public float yPlacement;
  132. public float xAdvance;
  133. public float yAdvance;
  134. internal GlyphValueRecord_Legacy(UnityEngine.TextCore.LowLevel.GlyphValueRecord valueRecord)
  135. {
  136. this.xPlacement = valueRecord.xPlacement;
  137. this.yPlacement = valueRecord.yPlacement;
  138. this.xAdvance = valueRecord.xAdvance;
  139. this.yAdvance = valueRecord.yAdvance;
  140. }
  141. public static GlyphValueRecord_Legacy operator +(GlyphValueRecord_Legacy a, GlyphValueRecord_Legacy b)
  142. {
  143. GlyphValueRecord_Legacy c;
  144. c.xPlacement = a.xPlacement + b.xPlacement;
  145. c.yPlacement = a.yPlacement + b.yPlacement;
  146. c.xAdvance = a.xAdvance + b.xAdvance;
  147. c.yAdvance = a.yAdvance + b.yAdvance;
  148. return c;
  149. }
  150. }
  151. [Serializable]
  152. public class KerningPair
  153. {
  154. /// <summary>
  155. /// The first glyph part of a kerning pair.
  156. /// </summary>
  157. public uint firstGlyph
  158. {
  159. get { return m_FirstGlyph; }
  160. set { m_FirstGlyph = value; }
  161. }
  162. [FormerlySerializedAs("AscII_Left")]
  163. [SerializeField]
  164. private uint m_FirstGlyph;
  165. /// <summary>
  166. /// The positional adjustment of the first glyph.
  167. /// </summary>
  168. public GlyphValueRecord_Legacy firstGlyphAdjustments
  169. {
  170. get { return m_FirstGlyphAdjustments; }
  171. }
  172. [SerializeField]
  173. private GlyphValueRecord_Legacy m_FirstGlyphAdjustments;
  174. /// <summary>
  175. /// The second glyph part of a kerning pair.
  176. /// </summary>
  177. public uint secondGlyph
  178. {
  179. get { return m_SecondGlyph; }
  180. set { m_SecondGlyph = value; }
  181. }
  182. [FormerlySerializedAs("AscII_Right")]
  183. [SerializeField]
  184. private uint m_SecondGlyph;
  185. /// <summary>
  186. /// The positional adjustment of the second glyph.
  187. /// </summary>
  188. public GlyphValueRecord_Legacy secondGlyphAdjustments
  189. {
  190. get { return m_SecondGlyphAdjustments; }
  191. }
  192. [SerializeField]
  193. private GlyphValueRecord_Legacy m_SecondGlyphAdjustments;
  194. [FormerlySerializedAs("XadvanceOffset")]
  195. public float xOffset;
  196. internal static KerningPair empty = new KerningPair(0, new GlyphValueRecord_Legacy(), 0, new GlyphValueRecord_Legacy());
  197. /// <summary>
  198. /// Determines if the Character Spacing property of the text object will affect the kerning pair.
  199. /// This is mostly relevant when using Diacritical marks to prevent Character Spacing from altering the
  200. /// </summary>
  201. public bool ignoreSpacingAdjustments
  202. {
  203. get { return m_IgnoreSpacingAdjustments; }
  204. }
  205. [SerializeField]
  206. private bool m_IgnoreSpacingAdjustments = false;
  207. public KerningPair()
  208. {
  209. m_FirstGlyph = 0;
  210. m_FirstGlyphAdjustments = new GlyphValueRecord_Legacy();
  211. m_SecondGlyph = 0;
  212. m_SecondGlyphAdjustments = new GlyphValueRecord_Legacy();
  213. }
  214. public KerningPair(uint left, uint right, float offset)
  215. {
  216. firstGlyph = left;
  217. m_SecondGlyph = right;
  218. xOffset = offset;
  219. }
  220. public KerningPair(uint firstGlyph, GlyphValueRecord_Legacy firstGlyphAdjustments, uint secondGlyph, GlyphValueRecord_Legacy secondGlyphAdjustments)
  221. {
  222. m_FirstGlyph = firstGlyph;
  223. m_FirstGlyphAdjustments = firstGlyphAdjustments;
  224. m_SecondGlyph = secondGlyph;
  225. m_SecondGlyphAdjustments = secondGlyphAdjustments;
  226. }
  227. internal void ConvertLegacyKerningData()
  228. {
  229. m_FirstGlyphAdjustments.xAdvance = xOffset;
  230. //xOffset = 0;
  231. }
  232. }
  233. [Serializable]
  234. public class KerningTable
  235. {
  236. public List<KerningPair> kerningPairs;
  237. public KerningTable()
  238. {
  239. kerningPairs = new List<KerningPair>();
  240. }
  241. public void AddKerningPair()
  242. {
  243. if (kerningPairs.Count == 0)
  244. {
  245. kerningPairs.Add(new KerningPair(0, 0, 0));
  246. }
  247. else
  248. {
  249. uint left = kerningPairs.Last().firstGlyph;
  250. uint right = kerningPairs.Last().secondGlyph;
  251. float xoffset = kerningPairs.Last().xOffset;
  252. kerningPairs.Add(new KerningPair(left, right, xoffset));
  253. }
  254. }
  255. /// <summary>
  256. /// Add Kerning Pair
  257. /// </summary>
  258. /// <param name="first">First glyph</param>
  259. /// <param name="second">Second glyph</param>
  260. /// <param name="offset">xAdvance value</param>
  261. /// <returns></returns>
  262. public int AddKerningPair(uint first, uint second, float offset)
  263. {
  264. int index = kerningPairs.FindIndex(item => item.firstGlyph == first && item.secondGlyph == second);
  265. if (index == -1)
  266. {
  267. kerningPairs.Add(new KerningPair(first, second, offset));
  268. return 0;
  269. }
  270. // Return -1 if Kerning Pair already exists.
  271. return -1;
  272. }
  273. /// <summary>
  274. /// Add Glyph pair adjustment record
  275. /// </summary>
  276. /// <param name="firstGlyph">The first glyph</param>
  277. /// <param name="firstGlyphAdjustments">Adjustment record for the first glyph</param>
  278. /// <param name="secondGlyph">The second glyph</param>
  279. /// <param name="secondGlyphAdjustments">Adjustment record for the second glyph</param>
  280. /// <returns></returns>
  281. public int AddGlyphPairAdjustmentRecord(uint first, GlyphValueRecord_Legacy firstAdjustments, uint second, GlyphValueRecord_Legacy secondAdjustments)
  282. {
  283. int index = kerningPairs.FindIndex(item => item.firstGlyph == first && item.secondGlyph == second);
  284. if (index == -1)
  285. {
  286. kerningPairs.Add(new KerningPair(first, firstAdjustments, second, secondAdjustments));
  287. return 0;
  288. }
  289. // Return -1 if Kerning Pair already exists.
  290. return -1;
  291. }
  292. public void RemoveKerningPair(int left, int right)
  293. {
  294. int index = kerningPairs.FindIndex(item => item.firstGlyph == left && item.secondGlyph == right);
  295. if (index != -1)
  296. kerningPairs.RemoveAt(index);
  297. }
  298. public void RemoveKerningPair(int index)
  299. {
  300. kerningPairs.RemoveAt(index);
  301. }
  302. public void SortKerningPairs()
  303. {
  304. // Sort List of Kerning Info
  305. if (kerningPairs.Count > 0)
  306. kerningPairs = kerningPairs.OrderBy(s => s.firstGlyph).ThenBy(s => s.secondGlyph).ToList();
  307. }
  308. }
  309. public static class TMP_FontUtilities
  310. {
  311. private static List<int> k_searchedFontAssets;
  312. /// <summary>
  313. /// Search through the given font and its fallbacks for the specified character.
  314. /// </summary>
  315. /// <param name="font">The font asset to search for the given character.</param>
  316. /// <param name="unicode">The character to find.</param>
  317. /// <param name="character">out parameter containing the glyph for the specified character (if found).</param>
  318. /// <returns></returns>
  319. public static TMP_FontAsset SearchForCharacter(TMP_FontAsset font, uint unicode, out TMP_Character character)
  320. {
  321. if (k_searchedFontAssets == null)
  322. k_searchedFontAssets = new List<int>();
  323. k_searchedFontAssets.Clear();
  324. return SearchForCharacterInternal(font, unicode, out character);
  325. }
  326. /// <summary>
  327. /// Search through the given list of fonts and their possible fallbacks for the specified character.
  328. /// </summary>
  329. /// <param name="fonts"></param>
  330. /// <param name="unicode"></param>
  331. /// <param name="character"></param>
  332. /// <returns></returns>
  333. public static TMP_FontAsset SearchForCharacter(List<TMP_FontAsset> fonts, uint unicode, out TMP_Character character)
  334. {
  335. return SearchForCharacterInternal(fonts, unicode, out character);
  336. }
  337. private static TMP_FontAsset SearchForCharacterInternal(TMP_FontAsset font, uint unicode, out TMP_Character character)
  338. {
  339. character = null;
  340. if (font == null) return null;
  341. if (font.characterLookupTable.TryGetValue(unicode, out character))
  342. {
  343. return font;
  344. }
  345. else if (font.fallbackFontAssetTable != null && font.fallbackFontAssetTable.Count > 0)
  346. {
  347. for (int i = 0; i < font.fallbackFontAssetTable.Count && character == null; i++)
  348. {
  349. TMP_FontAsset temp = font.fallbackFontAssetTable[i];
  350. if (temp == null) continue;
  351. int id = temp.GetInstanceID();
  352. // Skip over the fallback font asset in the event it is null or if already searched.
  353. if (k_searchedFontAssets.Contains(id)) continue;
  354. // Add to list of font assets already searched.
  355. k_searchedFontAssets.Add(id);
  356. temp = SearchForCharacterInternal(temp, unicode, out character);
  357. if (temp != null)
  358. return temp;
  359. }
  360. }
  361. return null;
  362. }
  363. private static TMP_FontAsset SearchForCharacterInternal(List<TMP_FontAsset> fonts, uint unicode, out TMP_Character character)
  364. {
  365. character = null;
  366. if (fonts != null && fonts.Count > 0)
  367. {
  368. for (int i = 0; i < fonts.Count; i++)
  369. {
  370. TMP_FontAsset fontAsset = SearchForCharacterInternal(fonts[i], unicode, out character);
  371. if (fontAsset != null)
  372. return fontAsset;
  373. }
  374. }
  375. return null;
  376. }
  377. }
  378. }