- Home /
How to determine font metrics?
Hello, I'm currently making a GUI framework and doing all the rendering with the GL class. To render text, I use GL and the CharacterInfo class, which works very well. The hard part is, how do I go about formatting the text? I need access to the font metrics (baseline, ascend, descend etc) so I know where the top, bottom and baseline of the font is. I think it's actually pretty absurd that Unity doesn't provide access to these values, since they are used under the hood already.
So does anybody know if there is a way I can access them? Maybe via Reflection? Because if I can't, my only option would be to write an AssetPostProcessor and read the actual font file, then store the metrics in a ScriptableObject, which is a pretty ugly solution. And would also cause problems when the user tries to use one of Unity's fonts.
I would like to avoid doing that, but I'll probably end up having to. Everything in Unity ends up an ugly mess for me because of all the limitations. But if anyone has any insight that would be great!
Answer by janzdott · Jul 12, 2013 at 08:05 PM
I just threw together a method which should provide a less ugly solution. The method determines the normalized ascend and descend metrics for a given font. The results aren't exact, but they should be very close. Close enough to allow me to implement good text formatting in my GUI framework. For Arial, it figures the ascend and descend to be approximatedly 0.774 and 0.226 respectively. And the code is below.
public static void GetFontMetrics(Font font, int fontSize) {
//Get a string containing all characters
StringBuilder stringBuilder = new StringBuilder();
for (int i = 32; i < 127; i++) {
stringBuilder.Append((char)i);
}
string allCharacters = stringBuilder.ToString();
//Make sure all characters are included in font texture
font.RequestCharactersInTexture(allCharacters);
//Dictionary keeps track of each different baseline, and how many characters use it
Dictionary<float, int> baseLines = new Dictionary<float, int>();
//The height of the highest and lowest characters
float highest = float.NegativeInfinity;
float lowest = float.PositiveInfinity;
//Loop through all characters
for (int i = 0; i < allCharacters.Length; i++) {
CharacterInfo info;
bool exists = font.GetCharacterInfo(allCharacters[i], out info, fontSize);
//Make sure character exists in font texture
if (exists) {
//Pixel values for top and bottom of character
float bottom = info.vert.height + info.vert.y;
float top = info.vert.y;
//Add bottom of character to baselines
if (baseLines.ContainsKey(bottom)) {
baseLines[bottom]++;
}
else {
baseLines[bottom] = 1;
}
//Is this the highest or lowest character so far?
if (top > highest) {
highest = top;
}
if (bottom < lowest) {
lowest = bottom;
}
}
}
//Loop through all different baselines.
//The one used the most is the baseline
int highestBaseLineCount = 0;
float baseLine = 0;
foreach (KeyValuePair<float, int> pair in baseLines) {
if (pair.Value > highestBaseLineCount) {
highestBaseLineCount = pair.Value;
baseLine = pair.Key;
}
}
//Calculate metrics
float ascend = (highest - baseLine) / (highest - lowest);
float descend = (baseLine - lowest) / (highest - lowest);
Debug.Log(string.Format("Ascend: {0}", ascend));
Debug.Log(string.Format("Descend: {0}", descend));
}
Your answer

Follow this Question
Related Questions
Subscripts and superscripts in Unity new GUI 2 Answers
Change Font Size of GUI Table 0 Answers
Fonts in Android... 0 Answers
GUIBox fontSize without changing other labels? 3 Answers
How do I increase font size properly? 4 Answers