Hue Preserving Color Blending
TMPro_FontUtilities.cs
1 using UnityEngine;
2 using UnityEngine.Serialization;
3 using System;
4 using System.Collections;
5 using System.Collections.Generic;
6 using System.Linq;
7 
8 
9 namespace TMPro
10 {
14  [Serializable]
15  public class FaceInfo
16  {
17  public string Name;
18  public float PointSize;
19  public float Scale;
20 
21  public int CharacterCount;
22 
23  public float LineHeight;
24  public float Baseline;
25  public float Ascender;
26  public float CapHeight;
27  public float Descender;
28  public float CenterLine;
29 
30  public float SuperscriptOffset;
31  public float SubscriptOffset;
32  public float SubSize;
33 
34  public float Underline;
35  public float UnderlineThickness;
36 
37  public float strikethrough;
38  public float strikethroughThickness;
39 
40  public float TabWidth;
41 
42  public float Padding;
43  public float AtlasWidth;
44  public float AtlasHeight;
45  }
46 
47 
48  // Class which contains the Glyph Info / Character definition for each character contained in the font asset.
49  [Serializable]
50  public class TMP_Glyph : TMP_TextElement
51  {
57  public static TMP_Glyph Clone(TMP_Glyph source)
58  {
59  TMP_Glyph copy = new TMP_Glyph();
60 
61  copy.id = source.id;
62  copy.x = source.x;
63  copy.y = source.y;
64  copy.width = source.width;
65  copy.height = source.height;
66  copy.xOffset = source.xOffset;
67  copy.yOffset = source.yOffset;
68  copy.xAdvance = source.xAdvance;
69  copy.scale = source.scale;
70 
71  return copy;
72  }
73  }
74 
75 
76  // Structure which holds the font creation settings
77  [Serializable]
79  {
80  public string sourceFontFileName;
81  public string sourceFontFileGUID;
82  public int pointSizeSamplingMode;
83  public int pointSize;
84  public int padding;
85  public int packingMode;
86  public int atlasWidth;
87  public int atlasHeight;
88  public int characterSetSelectionMode;
89  public string characterSequence;
90  public string referencedFontAssetGUID;
91  public string referencedTextAssetGUID;
92  public int fontStyle;
93  public float fontStyleModifier;
94  public int renderMode;
95  public bool includeFontFeatures;
96  }
97 
98 
99  public struct KerningPairKey
100  {
101  public uint ascii_Left;
102  public uint ascii_Right;
103  public uint key;
104 
105  public KerningPairKey(uint ascii_left, uint ascii_right)
106  {
107  ascii_Left = ascii_left;
108  ascii_Right = ascii_right;
109  key = (ascii_right << 16) + ascii_left;
110  }
111  }
112 
116  [Serializable]
117  public struct GlyphValueRecord
118  {
119  public float xPlacement;
120  public float yPlacement;
121  public float xAdvance;
122  public float yAdvance;
123 
124  public static GlyphValueRecord operator +(GlyphValueRecord a, GlyphValueRecord b)
125  {
127  c.xPlacement = a.xPlacement + b.xPlacement;
128  c.yPlacement = a.yPlacement + b.yPlacement;
129  c.xAdvance = a.xAdvance + b.xAdvance;
130  c.yAdvance = a.yAdvance + b.yAdvance;
131 
132  return c;
133  }
134  }
135 
136 
137  [Serializable]
138  public class KerningPair
139  {
143  public uint firstGlyph
144  {
145  get { return m_FirstGlyph; }
146  set { m_FirstGlyph = value; }
147  }
148  [FormerlySerializedAs("AscII_Left")]
149  [SerializeField]
150  private uint m_FirstGlyph;
151 
156  {
157  get { return m_FirstGlyphAdjustments; }
158  }
159  [SerializeField]
160  private GlyphValueRecord m_FirstGlyphAdjustments;
161 
165  public uint secondGlyph
166  {
167  get { return m_SecondGlyph; }
168  set { m_SecondGlyph = value; }
169  }
170  [FormerlySerializedAs("AscII_Right")]
171  [SerializeField]
172  private uint m_SecondGlyph;
173 
178  {
179  get { return m_SecondGlyphAdjustments; }
180  }
181  [SerializeField]
182  private GlyphValueRecord m_SecondGlyphAdjustments;
183 
184  [FormerlySerializedAs("XadvanceOffset")]
185  public float xOffset;
186 
187 
188  public KerningPair()
189  {
190  m_FirstGlyph = 0;
191  m_FirstGlyphAdjustments = new GlyphValueRecord();
192 
193  m_SecondGlyph = 0;
194  m_SecondGlyphAdjustments = new GlyphValueRecord();
195  }
196 
197  public KerningPair(uint left, uint right, float offset)
198  {
199  firstGlyph = left;
200  m_SecondGlyph = right;
201  xOffset = offset;
202  }
203 
204  public KerningPair(uint firstGlyph, GlyphValueRecord firstGlyphAdjustments, uint secondGlyph, GlyphValueRecord secondGlyphAdjustments)
205  {
206  m_FirstGlyph = firstGlyph;
207  m_FirstGlyphAdjustments = firstGlyphAdjustments;
208  m_SecondGlyph = secondGlyph;
209  m_SecondGlyphAdjustments = secondGlyphAdjustments;
210  }
211 
212  internal void ConvertLegacyKerningData()
213  {
214  m_FirstGlyphAdjustments.xAdvance = xOffset;
215  //xOffset = 0;
216  }
217 
218  }
219 
220 
221  [Serializable]
222  public class KerningTable
223  {
224  public List<KerningPair> kerningPairs;
225 
226 
227  public KerningTable()
228  {
229  kerningPairs = new List<KerningPair>();
230  }
231 
232 
233  public void AddKerningPair()
234  {
235  if (kerningPairs.Count == 0)
236  {
237  kerningPairs.Add(new KerningPair(0, 0, 0));
238  }
239  else
240  {
241  uint left = kerningPairs.Last().firstGlyph;
242  uint right = kerningPairs.Last().secondGlyph;
243  float xoffset = kerningPairs.Last().xOffset;
244 
245  kerningPairs.Add(new KerningPair(left, right, xoffset));
246  }
247  }
248 
249 
257  public int AddKerningPair(uint first, uint second, float offset)
258  {
259  int index = kerningPairs.FindIndex(item => item.firstGlyph == first && item.secondGlyph == second);
260 
261  if (index == -1)
262  {
263  kerningPairs.Add(new KerningPair(first, second, offset));
264  return 0;
265  }
266 
267  // Return -1 if Kerning Pair already exists.
268  return -1;
269  }
270 
279  public int AddGlyphPairAdjustmentRecord(uint first, GlyphValueRecord firstAdjustments, uint second, GlyphValueRecord secondAdjustments)
280  {
281  int index = kerningPairs.FindIndex(item => item.firstGlyph == first && item.secondGlyph == second);
282 
283  if (index == -1)
284  {
285  kerningPairs.Add(new KerningPair(first, firstAdjustments, second, secondAdjustments));
286  return 0;
287  }
288 
289  // Return -1 if Kerning Pair already exists.
290  return -1;
291  }
292 
293  public void RemoveKerningPair(int left, int right)
294  {
295  int index = kerningPairs.FindIndex(item => item.firstGlyph == left && item.secondGlyph == right);
296 
297  if (index != -1)
298  kerningPairs.RemoveAt(index);
299  }
300 
301 
302  public void RemoveKerningPair(int index)
303  {
304  kerningPairs.RemoveAt(index);
305  }
306 
307 
308  public void SortKerningPairs()
309  {
310  // Sort List of Kerning Info
311  if (kerningPairs.Count > 0)
312  kerningPairs = kerningPairs.OrderBy(s => s.firstGlyph).ThenBy(s => s.secondGlyph).ToList();
313  }
314  }
315 
316 
317  public static class TMP_FontUtilities
318  {
319  private static List<int> k_searchedFontAssets;
320 
328  public static TMP_FontAsset SearchForGlyph(TMP_FontAsset font, int character, out TMP_Glyph glyph)
329  {
330  if (k_searchedFontAssets == null)
331  k_searchedFontAssets = new List<int>();
332 
333  k_searchedFontAssets.Clear();
334 
335  return SearchForGlyphInternal(font, character, out glyph);
336  }
337 
338 
346  public static TMP_FontAsset SearchForGlyph(List<TMP_FontAsset> fonts, int character, out TMP_Glyph glyph)
347  {
348  return SearchForGlyphInternal(fonts, character, out glyph);
349  }
350 
351 
352  private static TMP_FontAsset SearchForGlyphInternal (TMP_FontAsset font, int character, out TMP_Glyph glyph)
353  {
354  glyph = null;
355 
356  if (font == null) return null;
357 
358  if (font.characterDictionary.TryGetValue(character, out glyph))
359  {
360  return font;
361  }
362  else if (font.fallbackFontAssets != null && font.fallbackFontAssets.Count > 0)
363  {
364  for (int i = 0; i < font.fallbackFontAssets.Count && glyph == null; i++)
365  {
366  TMP_FontAsset temp = font.fallbackFontAssets[i];
367  if (temp == null) continue;
368 
369  int id = temp.GetInstanceID();
370 
371  // Skip over the fallback font asset in the event it is null or if already searched.
372  if (k_searchedFontAssets.Contains(id)) continue;
373 
374  // Add to list of font assets already searched.
375  k_searchedFontAssets.Add(id);
376 
377  temp = SearchForGlyphInternal(temp, character, out glyph);
378 
379  if (temp != null)
380  return temp;
381  }
382  }
383 
384  return null;
385  }
386 
387 
388  private static TMP_FontAsset SearchForGlyphInternal(List<TMP_FontAsset> fonts, int character, out TMP_Glyph glyph)
389  {
390  glyph = null;
391 
392  if (fonts != null && fonts.Count > 0)
393  {
394  for (int i = 0; i < fonts.Count; i++)
395  {
396  TMP_FontAsset fontAsset = SearchForGlyphInternal(fonts[i], character, out glyph);
397 
398  if (fontAsset != null)
399  return fontAsset;
400  }
401  }
402 
403  return null;
404  }
405  }
406 
407 
408 
409 }
Positional adjustments of a glyph
int AddKerningPair(uint first, uint second, float offset)
Add Kerning Pair
GlyphValueRecord secondGlyphAdjustments
The positional adjustment of the second glyph.
GlyphValueRecord firstGlyphAdjustments
The positional adjustment of the first glyph.
int AddGlyphPairAdjustmentRecord(uint first, GlyphValueRecord firstAdjustments, uint second, GlyphValueRecord secondAdjustments)
Add Glyph pair adjustment record
Base class for all text elements like characters (glyphs) and sprites.
static TMP_Glyph Clone(TMP_Glyph source)
Function to create a deep copy of a GlyphInfo.
uint secondGlyph
The second glyph part of a kerning pair.
uint firstGlyph
The first glyph part of a kerning pair.
Class that contains the basic information about the font.