You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

408 lines
12 KiB

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