Hue Preserving Color Blending
TMP_FontAsset.cs
1 using System;
2 using UnityEngine;
3 using System.Collections;
4 using System.Collections.Generic;
5 using System.Linq;
6 
7 
8 namespace TMPro
9 {
10 
14  [Serializable]
15  public struct TMP_FontWeights
16  {
17  public TMP_FontAsset regularTypeface;
18  public TMP_FontAsset italicTypeface;
19  }
20 
21 
22  [Serializable]
23  public class TMP_FontAsset : TMP_Asset
24  {
28  public static TMP_FontAsset defaultFontAsset
29  {
30  get
31  {
32  if (s_defaultFontAsset == null)
33  {
34  s_defaultFontAsset = Resources.Load<TMP_FontAsset>("Fonts & Materials/LiberationSans SDF");
35  }
36 
37  return s_defaultFontAsset;
38  }
39  }
40  private static TMP_FontAsset s_defaultFontAsset;
41 
42 
43  public enum FontAssetTypes { None = 0, SDF = 1, Bitmap = 2 };
44  public FontAssetTypes fontAssetType;
45 
49  public FaceInfo fontInfo
50  { get { return m_fontInfo; } }
51 
52  [SerializeField]
53  private FaceInfo m_fontInfo;
54 
55  [SerializeField]
56  public Texture2D atlas; // Should add a property to make this read-only.
57 
58 
59  // Glyph Info
60  [SerializeField]
61  private List<TMP_Glyph> m_glyphInfoList;
62 
63  public Dictionary<int, TMP_Glyph> characterDictionary
64  {
65  get
66  {
67  if (m_characterDictionary == null)
69 
70  return m_characterDictionary;
71  }
72  }
73  private Dictionary<int, TMP_Glyph> m_characterDictionary;
74 
78  public Dictionary<int, KerningPair> kerningDictionary
79  {
80  get { return m_kerningDictionary; }
81  }
82  private Dictionary<int, KerningPair> m_kerningDictionary;
83 
88  {
89  get { return m_kerningInfo; }
90  }
91 
92  [SerializeField]
93  private KerningTable m_kerningInfo;
94 
95  [SerializeField]
96  #pragma warning disable 0169 // Property is used to create an empty Kerning Pair in the editor.
97  private KerningPair m_kerningPair; // Used for creating a new kerning pair in Editor Panel.
98 
102  [SerializeField]
103  public List<TMP_FontAsset> fallbackFontAssets;
104 
109  {
110  get { return m_CreationSettings; }
111  set { m_CreationSettings = value; }
112  }
113  [SerializeField]
114  public FontAssetCreationSettings m_CreationSettings;
115 
116  // FONT WEIGHTS
117  [SerializeField]
118  public TMP_FontWeights[] fontWeights = new TMP_FontWeights[10];
119 
120  private int[] m_characterSet; // Array containing all the characters in this font asset.
121 
122  public float normalStyle = 0;
123  public float normalSpacingOffset = 0;
124 
125  public float boldStyle = 0.75f;
126  public float boldSpacing = 7f;
127  public byte italicStyle = 35;
128  public byte tabSize = 10;
129 
130  private byte m_oldTabSize;
131 
132  void OnEnable()
133  {
134  //Debug.Log("OnEnable has been called on " + this.name);
135  }
136 
137 
138  void OnDisable()
139  {
140  //Debug.Log("TextMeshPro Font Asset [" + this.name + "] has been disabled!");
141  }
142 
143 
144 #if UNITY_EDITOR
145  void OnValidate()
149  {
150  if (m_oldTabSize != tabSize)
151  {
152  m_oldTabSize = tabSize;
154  }
155  }
156 #endif
157 
158 
163  public void AddFaceInfo(FaceInfo faceInfo)
164  {
165  m_fontInfo = faceInfo;
166  }
167 
168 
173  public void AddGlyphInfo(TMP_Glyph[] glyphInfo)
174  {
175  m_glyphInfoList = new List<TMP_Glyph>();
176  int characterCount = glyphInfo.Length;
177 
178  m_fontInfo.CharacterCount = characterCount;
179  m_characterSet = new int[characterCount];
180 
181  for (int i = 0; i < characterCount; i++)
182  {
183  TMP_Glyph g = new TMP_Glyph();
184  g.id = glyphInfo[i].id;
185  g.x = glyphInfo[i].x;
186  g.y = glyphInfo[i].y;
187  g.width = glyphInfo[i].width;
188  g.height = glyphInfo[i].height;
189  g.xOffset = glyphInfo[i].xOffset;
190  g.yOffset = (glyphInfo[i].yOffset);
191  g.xAdvance = glyphInfo[i].xAdvance;
192  g.scale = 1;
193 
194  m_glyphInfoList.Add(g);
195 
196  // While iterating through list of glyphs, find the Descender & Ascender for this GlyphSet.
197  //m_fontInfo.Ascender = Mathf.Max(m_fontInfo.Ascender, glyphInfo[i].yOffset);
198  //m_fontInfo.Descender = Mathf.Min(m_fontInfo.Descender, glyphInfo[i].yOffset - glyphInfo[i].height);
199  //Debug.Log(m_fontInfo.Ascender + " " + m_fontInfo.Descender);
200  m_characterSet[i] = g.id; // Add Character ID to Array to make it easier to get the kerning pairs.
201  }
202 
203  // Sort List by ID.
204  m_glyphInfoList = m_glyphInfoList.OrderBy(s => s.id).ToList();
205  }
206 
207 
212  public void AddKerningInfo(KerningTable kerningTable)
213  {
214  m_kerningInfo = kerningTable;
215  }
216 
217 
221  public void ReadFontDefinition()
222  {
223  //Debug.Log("Reading Font Definition for " + this.name + ".");
224  // Make sure that we have a Font Asset file assigned.
225  if (m_fontInfo == null)
226  {
227  return;
228  }
229 
230  // Check Font Asset type
231  //Debug.Log(name + " " + fontAssetType);
232 
233  // Create new instance of GlyphInfo Dictionary for fast access to glyph info.
234  m_characterDictionary = new Dictionary<int, TMP_Glyph>();
235  for (int i = 0; i < m_glyphInfoList.Count; i++)
236  {
237  TMP_Glyph glyph = m_glyphInfoList[i];
238 
239  if (!m_characterDictionary.ContainsKey(glyph.id))
240  m_characterDictionary.Add(glyph.id, glyph);
241 
242  // Compatibility
243  if (glyph.scale == 0) glyph.scale = 1;
244  }
245 
246 
247  //Debug.Log("PRE: BaseLine:" + m_fontInfo.Baseline + " Ascender:" + m_fontInfo.Ascender + " Descender:" + m_fontInfo.Descender); // + " Centerline:" + m_fontInfo.CenterLine);
248 
249  TMP_Glyph temp_charInfo = new TMP_Glyph();
250 
251  // Add Character (10) LineFeed, (13) Carriage Return & Space (32) to Dictionary if they don't exists.
252  if (m_characterDictionary.ContainsKey(32))
253  {
254  m_characterDictionary[32].width = m_characterDictionary[32].xAdvance; // m_fontInfo.Ascender / 5;
255  m_characterDictionary[32].height = m_fontInfo.Ascender - m_fontInfo.Descender;
256  m_characterDictionary[32].yOffset= m_fontInfo.Ascender;
257  m_characterDictionary[32].scale = 1;
258  }
259  else
260  {
261  //Debug.Log("Adding Character 32 (Space) to Dictionary for Font (" + m_fontInfo.Name + ").");
262  temp_charInfo = new TMP_Glyph();
263  temp_charInfo.id = 32;
264  temp_charInfo.x = 0;
265  temp_charInfo.y = 0;
266  temp_charInfo.width = m_fontInfo.Ascender / 5;
267  temp_charInfo.height = m_fontInfo.Ascender - m_fontInfo.Descender;
268  temp_charInfo.xOffset = 0;
269  temp_charInfo.yOffset = m_fontInfo.Ascender;
270  temp_charInfo.xAdvance = m_fontInfo.PointSize / 4;
271  temp_charInfo.scale = 1;
272  m_characterDictionary.Add(32, temp_charInfo);
273  }
274 
275  // Add Non-Breaking Space (160)
276  if (!m_characterDictionary.ContainsKey(160))
277  {
278  temp_charInfo = TMP_Glyph.Clone(m_characterDictionary[32]);
279  m_characterDictionary.Add(160, temp_charInfo);
280  }
281 
282  // Add Zero Width Space (8203)
283  if (!m_characterDictionary.ContainsKey(8203))
284  {
285  temp_charInfo = TMP_Glyph.Clone(m_characterDictionary[32]);
286  temp_charInfo.width = 0;
287  temp_charInfo.xAdvance = 0;
288  m_characterDictionary.Add(8203, temp_charInfo);
289  }
290 
291  //Add Zero Width no-break space (8288)
292  if (!m_characterDictionary.ContainsKey(8288))
293  {
294  temp_charInfo = TMP_Glyph.Clone(m_characterDictionary[32]);
295  temp_charInfo.width = 0;
296  temp_charInfo.xAdvance = 0;
297  m_characterDictionary.Add(8288, temp_charInfo);
298  }
299 
300  // Add Linefeed (10)
301  if (m_characterDictionary.ContainsKey(10) == false)
302  {
303  //Debug.Log("Adding Character 10 (Linefeed) to Dictionary for Font (" + m_fontInfo.Name + ").");
304 
305  temp_charInfo = new TMP_Glyph();
306  temp_charInfo.id = 10;
307  temp_charInfo.x = 0; // m_characterDictionary[32].x;
308  temp_charInfo.y = 0; // m_characterDictionary[32].y;
309  temp_charInfo.width = 10; // m_characterDictionary[32].width;
310  temp_charInfo.height = m_characterDictionary[32].height;
311  temp_charInfo.xOffset = 0; // m_characterDictionary[32].xOffset;
312  temp_charInfo.yOffset = m_characterDictionary[32].yOffset;
313  temp_charInfo.xAdvance = 0;
314  temp_charInfo.scale = 1;
315  m_characterDictionary.Add(10, temp_charInfo);
316 
317  if (!m_characterDictionary.ContainsKey(13))
318  m_characterDictionary.Add(13, temp_charInfo);
319  }
320 
321  // Add Tab Character to Dictionary. Tab is Tab Size * Space Character Width.
322  if (m_characterDictionary.ContainsKey(9) == false)
323  {
324  //Debug.Log("Adding Character 9 (Tab) to Dictionary for Font (" + m_fontInfo.Name + ").");
325 
326  temp_charInfo = new TMP_Glyph();
327  temp_charInfo.id = 9;
328  temp_charInfo.x = m_characterDictionary[32].x;
329  temp_charInfo.y = m_characterDictionary[32].y;
330  temp_charInfo.width = m_characterDictionary[32].width * tabSize + (m_characterDictionary[32].xAdvance - m_characterDictionary[32].width) * (tabSize - 1);
331  temp_charInfo.height = m_characterDictionary[32].height;
332  temp_charInfo.xOffset = m_characterDictionary[32].xOffset;
333  temp_charInfo.yOffset = m_characterDictionary[32].yOffset;
334  temp_charInfo.xAdvance = m_characterDictionary[32].xAdvance * tabSize;
335  temp_charInfo.scale = 1;
336  m_characterDictionary.Add(9, temp_charInfo);
337  }
338 
339  // Centerline is located at the center of character like { or in the middle of the lowercase o.
340  //m_fontInfo.CenterLine = m_characterDictionary[111].yOffset - m_characterDictionary[111].height * 0.5f;
341 
342  // Tab Width is using the same xAdvance as space (32).
343  m_fontInfo.TabWidth = m_characterDictionary[9].xAdvance;
344 
345  // Set Cap Height
346  if (m_fontInfo.CapHeight == 0 && m_characterDictionary.ContainsKey(72))
347  m_fontInfo.CapHeight = m_characterDictionary[72].yOffset;
348 
349  // Adjust Font Scale for compatibility reasons
350  if (m_fontInfo.Scale == 0)
351  m_fontInfo.Scale = 1.0f;
352 
353  // Set Strikethrough Offset (if needed)
354  if (m_fontInfo.strikethrough == 0)
355  m_fontInfo.strikethrough = m_fontInfo.CapHeight / 2.5f;
356 
357  // Set Padding value for legacy font assets.
358  if (m_fontInfo.Padding == 0)
359  {
360  if (material.HasProperty(ShaderUtilities.ID_GradientScale))
361  m_fontInfo.Padding = material.GetFloat(ShaderUtilities.ID_GradientScale) - 1;
362  }
363 
364  // Populate Dictionary with Kerning Information
365  m_kerningDictionary = new Dictionary<int, KerningPair>();
366  List<KerningPair> pairs = m_kerningInfo.kerningPairs;
367 
368  //Debug.Log(m_fontInfo.Name + " has " + pairs.Count + " Kerning Pairs.");
369  for (int i = 0; i < pairs.Count; i++)
370  {
371  KerningPair pair = pairs[i];
372 
373  // Convert legacy kerning data
374  if (pair.xOffset != 0)
375  pairs[i].ConvertLegacyKerningData();
376 
377  KerningPairKey uniqueKey = new KerningPairKey(pair.firstGlyph, pair.secondGlyph);
378 
379  if (m_kerningDictionary.ContainsKey((int)uniqueKey.key) == false)
380  {
381  m_kerningDictionary.Add((int)uniqueKey.key, pair);
382  }
383  else
384  {
386  Debug.LogWarning("Kerning Key for [" + uniqueKey.ascii_Left + "] and [" + uniqueKey.ascii_Right + "] already exists.");
387  }
388  }
389 
390 
391  // Compute Hashcode for the font asset name
392  hashCode = TMP_TextUtilities.GetSimpleHashCode(this.name);
393 
394  // Compute Hashcode for the material name
395  materialHashCode = TMP_TextUtilities.GetSimpleHashCode(material.name);
396 
397  // Unload font atlas texture
398  //ShaderUtilities.GetShaderPropertyIDs();
399  //Resources.UnloadAsset(material.GetTexture(ShaderUtilities.ID_MainTex));
400 
401  // Initialize Font Weights if needed
402  //InitializeFontWeights();
403  }
404 
405 
409  public void SortGlyphs()
410  {
411  if (m_glyphInfoList == null || m_glyphInfoList.Count == 0) return;
412 
413  m_glyphInfoList = m_glyphInfoList.OrderBy(item => item.id).ToList();
414  }
415 
416 
417 
423  public bool HasCharacter(int character)
424  {
425  if (m_characterDictionary == null)
426  return false;
427 
428  if (m_characterDictionary.ContainsKey(character))
429  return true;
430 
431  return false;
432  }
433 
434 
440  public bool HasCharacter(char character)
441  {
442  if (m_characterDictionary == null)
443  return false;
444 
445  if (m_characterDictionary.ContainsKey(character))
446  return true;
447 
448  return false;
449  }
450 
451 
458  public bool HasCharacter(char character, bool searchFallbacks)
459  {
460  // Read font asset definition if it hasn't already been done.
461  if (m_characterDictionary == null)
462  {
464 
465  if (m_characterDictionary == null)
466  return false;
467  }
468 
469  // Check font asset
470  if (m_characterDictionary.ContainsKey(character))
471  return true;
472 
473  if (searchFallbacks)
474  {
475  // Check font asset fallbacks
476  if (fallbackFontAssets != null && fallbackFontAssets.Count > 0)
477  {
478  for (int i = 0; i < fallbackFontAssets.Count && fallbackFontAssets[i] != null; i++)
479  {
480  if (fallbackFontAssets[i].HasCharacter_Internal(character, searchFallbacks))
481  return true;
482  }
483  }
484 
485  // Check general fallback font assets.
487  {
488  for (int i = 0; i < TMP_Settings.fallbackFontAssets.Count && TMP_Settings.fallbackFontAssets[i] != null; i++)
489  {
490  if (TMP_Settings.fallbackFontAssets[i].characterDictionary == null)
491  TMP_Settings.fallbackFontAssets[i].ReadFontDefinition();
492 
493  if (TMP_Settings.fallbackFontAssets[i].characterDictionary != null && TMP_Settings.fallbackFontAssets[i].HasCharacter_Internal(character, searchFallbacks))
494  return true;
495  }
496  }
497 
498  // Check TMP Settings Default Font Asset
499  if (TMP_Settings.defaultFontAsset != null)
500  {
501  if (TMP_Settings.defaultFontAsset.characterDictionary == null)
503 
504  if (TMP_Settings.defaultFontAsset.characterDictionary != null && TMP_Settings.defaultFontAsset.HasCharacter_Internal(character, searchFallbacks))
505  return true;
506  }
507  }
508 
509  return false;
510  }
511 
512 
520  bool HasCharacter_Internal(char character, bool searchFallbacks)
521  {
522  // Read font asset definition if it hasn't already been done.
523  if (m_characterDictionary == null)
524  {
526 
527  if (m_characterDictionary == null)
528  return false;
529  }
530 
531  // Check font asset
532  if (m_characterDictionary.ContainsKey(character))
533  return true;
534 
535  if (searchFallbacks)
536  {
537  // Check Font Asset Fallback fonts.
538  if (fallbackFontAssets != null && fallbackFontAssets.Count > 0)
539  {
540  for (int i = 0; i < fallbackFontAssets.Count && fallbackFontAssets[i] != null; i++)
541  {
542  if (fallbackFontAssets[i].HasCharacter_Internal(character, searchFallbacks))
543  return true;
544  }
545  }
546  }
547 
548  return false;
549  }
550 
551 
557  public bool HasCharacters(string text, out List<char> missingCharacters)
558  {
559  if (m_characterDictionary == null)
560  {
561  missingCharacters = null;
562  return false;
563  }
564 
565  missingCharacters = new List<char>();
566 
567  for (int i = 0; i < text.Length; i++)
568  {
569  if (!m_characterDictionary.ContainsKey(text[i]))
570  missingCharacters.Add(text[i]);
571  }
572 
573  if (missingCharacters.Count == 0)
574  return true;
575 
576  return false;
577  }
578 
579 
585  public bool HasCharacters(string text)
586  {
587  if (m_characterDictionary == null)
588  return false;
589 
590  for (int i = 0; i < text.Length; i++)
591  {
592  if (!m_characterDictionary.ContainsKey(text[i]))
593  return false;
594  }
595 
596  return true;
597  }
598 
599 
605  public static string GetCharacters(TMP_FontAsset fontAsset)
606  {
607  string characters = string.Empty;
608 
609  for (int i = 0; i < fontAsset.m_glyphInfoList.Count; i++)
610  {
611  characters += (char)fontAsset.m_glyphInfoList[i].id;
612  }
613 
614  return characters;
615  }
616 
617 
623  public static int[] GetCharactersArray(TMP_FontAsset fontAsset)
624  {
625  int[] characters = new int[fontAsset.m_glyphInfoList.Count];
626 
627  for (int i = 0; i < fontAsset.m_glyphInfoList.Count; i++)
628  {
629  characters[i] = fontAsset.m_glyphInfoList[i].id;
630  }
631 
632  return characters;
633  }
634 
635  }
636 }
bool HasCharacters(string text)
Function to check if certain characters exists in the font asset. Function returns false if any chara...
int hashCode
HashCode based on the name of the asset.
Definition: TMP_Asset.cs:13
List< TMP_FontAsset > fallbackFontAssets
List containing the Fallback font assets for this font.
void AddKerningInfo(KerningTable kerningTable)
bool HasCharacter(int character)
Function to check if a certain character exists in the font asset.
static int [] GetCharactersArray(TMP_FontAsset fontAsset)
Function which returns an array that contains all the characters from a font asset.
Contains the font asset for the specified font weight styles.
static TMP_FontAsset defaultFontAsset
Returns the Default Font Asset to be used by newly created text objects.
Definition: TMP_Settings.cs:98
void SortGlyphs()
Function to sort the list of glyphs.
Dictionary< int, KerningPair > kerningDictionary
Dictionary containing the kerning data
KerningTable kerningInfo
bool HasCharacters(string text, out List< char > missingCharacters)
Function to check if certain characters exists in the font asset. Function returns a list of missing ...
int materialHashCode
HashCode based on the name of the material assigned to this asset.
Definition: TMP_Asset.cs:23
bool HasCharacter(char character, bool searchFallbacks)
Function to check if a character is contained in the font asset with the option to also check through...
static TMP_FontAsset defaultFontAsset
Default Font Asset used as last resort when glyphs are missing.
bool HasCharacter(char character)
Function to check if a certain character exists in the font asset.
static TMP_Glyph Clone(TMP_Glyph source)
Function to create a deep copy of a GlyphInfo.
bool HasCharacter_Internal(char character, bool searchFallbacks)
Function to check if a character is contained in a font asset with the option to also check through f...
Material material
The material used by this asset.
Definition: TMP_Asset.cs:18
uint secondGlyph
The second glyph part of a kerning pair.
FontAssetCreationSettings creationSettings
The settings used in the Font Asset Creator when this font asset was created or edited.
void AddFaceInfo(FaceInfo faceInfo)
uint firstGlyph
The first glyph part of a kerning pair.
FaceInfo fontInfo
The general information about the font.
Class that contains the basic information about the font.
static bool warningsDisabled
Controls the display of warning message in the console.
Definition: TMP_Settings.cs:88
static string GetCharacters(TMP_FontAsset fontAsset)
Function to extract all the characters from a font asset.
void AddGlyphInfo(TMP_Glyph[] glyphInfo)
static List< TMP_FontAsset > fallbackFontAssets
Returns the list of Fallback Fonts defined in the TMP Settings file.