Skip to content

Commit

Permalink
Bitmap font parsing is now 2x faster.
Browse files Browse the repository at this point in the history
  • Loading branch information
vchelaru committed Mar 6, 2024
1 parent 7820137 commit 5fafb08
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 71 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public int GetXAdvanceInPixels(int lineHeightInPixels)
public int PageNumber;


public Dictionary<int, int> SecondLetterKearning = new Dictionary<int, int>();
public Dictionary<int, int> SecondLetterKearning;

#endregion

Expand Down
50 changes: 28 additions & 22 deletions Engines/FlatRedBallXNA/FlatRedBall/Graphics/BitmapFont.cs
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,10 @@ public void SetFontPattern(string fontPattern)
int secondCharacter = StringFunctions.GetIntAfter("second=", fontPattern, index);
int kearningAmount = StringFunctions.GetIntAfter("amount=", fontPattern, index);

if(mCharacterInfo[ID].SecondLetterKearning == null)
{
mCharacterInfo[ID].SecondLetterKearning = new Dictionary<int, int>();
}
mCharacterInfo[ID].SecondLetterKearning.Add(secondCharacter, kearningAmount);

index = fontPattern.IndexOf("first=", index + 1, StringComparison.Ordinal);
Expand Down Expand Up @@ -563,44 +567,46 @@ private Texture2D RenderToTexture2D(IEnumerable lines, HorizontalAlignment horiz
private BitmapCharacterInfo FillBitmapCharacterInfo(int characterID, string fontString, int textureWidth,
int textureHeight, int lineHeightInPixels, int startingIndex)
{
// Example:
// char id=101 x=158 y=85 width=5 height=7 xoffset=1 yoffset=6 xadvance=7 page=0 chnl=0
BitmapCharacterInfo characterInfoToReturn = new BitmapCharacterInfo();

int indexOfID = fontString.IndexOf("char id=" + characterID, startingIndex);

if (indexOfID != -1)
{
characterInfoToReturn.TULeft =
StringFunctions.GetIntAfter("x=", fontString, indexOfID) / (float)textureWidth;
characterInfoToReturn.TVTop =
StringFunctions.GetIntAfter("y=", fontString, indexOfID) / (float)textureHeight;
characterInfoToReturn.TURight = characterInfoToReturn.TULeft +
StringFunctions.GetIntAfter("width=", fontString, indexOfID) / (float)textureWidth;
characterInfoToReturn.TVBottom = characterInfoToReturn.TVTop +
StringFunctions.GetIntAfter("height=", fontString, indexOfID) / (float)textureHeight;
var x = StringFunctions.GetIntAfter("x=", fontString, ref indexOfID);
var y = StringFunctions.GetIntAfter("y=", fontString, ref indexOfID);
var width = StringFunctions.GetIntAfter("width=", fontString, ref indexOfID);
var height = StringFunctions.GetIntAfter("height=", fontString, ref indexOfID);
var xOffset = StringFunctions.GetIntAfter("xoffset=", fontString, ref indexOfID);
var yOffset = StringFunctions.GetIntAfter("yoffset=", fontString, ref indexOfID);
var xAdvance = StringFunctions.GetIntAfter("xadvance=", fontString, ref indexOfID);
var page = StringFunctions.GetIntAfter("page=", fontString, ref indexOfID);

characterInfoToReturn.DistanceFromTopOfLine = // 1 sclY means 2 height
2 * StringFunctions.GetIntAfter("yoffset=", fontString, indexOfID) / (float)lineHeightInPixels;
var textureWidthF = (float)textureWidth;
var textureHeightF = (float)textureHeight;

characterInfoToReturn.ScaleX = StringFunctions.GetIntAfter("width=", fontString, indexOfID) /
(float)lineHeightInPixels;
characterInfoToReturn.TULeft = x / textureWidthF;
characterInfoToReturn.TVTop = y / textureHeightF;

characterInfoToReturn.ScaleY = StringFunctions.GetIntAfter("height=", fontString, indexOfID) /
(float)lineHeightInPixels;
characterInfoToReturn.TURight = characterInfoToReturn.TULeft + width / textureWidthF;
characterInfoToReturn.TVBottom = characterInfoToReturn.TVTop + height / textureHeightF;

characterInfoToReturn.Spacing = 2 * StringFunctions.GetIntAfter("xadvance=", fontString, indexOfID) /
(float)lineHeightInPixels;
var lineHeightInPixelsF = (float)lineHeightInPixels;

characterInfoToReturn.XOffset = 2 * StringFunctions.GetIntAfter("xoffset=", fontString, indexOfID) /
(float)lineHeightInPixels;

characterInfoToReturn.PageNumber = StringFunctions.GetIntAfter("page=", fontString, indexOfID);
characterInfoToReturn.DistanceFromTopOfLine = // 1 sclY means 2 height
2 * yOffset / lineHeightInPixelsF;

characterInfoToReturn.ScaleX = width / lineHeightInPixelsF;

characterInfoToReturn.ScaleY = height / lineHeightInPixelsF;

// characterInfoToReturn.Spacing = 25 * StringFunctions.GetIntAfter("xadvance=", fontString, indexOfID) /
// (float)(textureWidth);
characterInfoToReturn.Spacing = 2 * xAdvance / lineHeightInPixelsF;

characterInfoToReturn.XOffset = 2 * xOffset / lineHeightInPixelsF;

characterInfoToReturn.PageNumber = page;
}

return characterInfoToReturn;
Expand Down
113 changes: 65 additions & 48 deletions Engines/FlatRedBallXNA/FlatRedBall/Utilities/StringFunctions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography.X509Certificates;


#if FRB_MDX
#elif SILVERLIGHT
Expand All @@ -21,7 +23,7 @@ public static class StringFunctions
{
#region Fields

static char[] sValidNumericalChars = { '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', ',' };
static HashSet<char> sValidNumericalChars = new HashSet<char> { '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', ',' };


#endregion
Expand Down Expand Up @@ -260,15 +262,7 @@ public static float GetFloatAfter(string stringToSearchFor, string whereToSearch

for (int i = startOfNumber; i < endOfNumber; i++)
{
bool found = false;
for (int indexInArray = 0; indexInArray < sValidNumericalChars.Length; indexInArray++)
{
if (whereToSearch[i] == sValidNumericalChars[indexInArray])
{
found = true;
break;
}
}
bool found = sValidNumericalChars.Contains(whereToSearch[i]);

if (!found)
{
Expand Down Expand Up @@ -353,71 +347,94 @@ public static int GetIntAfter(string stringToSearchFor, string whereToSearch, in
{
int startOfNumber = -1;
int endOfNumber = -1;
int enterAt = -1;
int carriageReturn = -1;
string substring = "uninitialized";
string substring = string.Empty;

try
{
int indexOf = whereToSearch.IndexOf(stringToSearchFor, startIndex);

if (indexOf != -1)
{
startOfNumber = indexOf + stringToSearchFor.Length;
endOfNumber = whereToSearch.IndexOf(' ', startOfNumber);
enterAt = whereToSearch.IndexOf('\n', startOfNumber);
endOfNumber = startIndex;

carriageReturn = whereToSearch.IndexOf('\r', startOfNumber);
if ( carriageReturn != -1 && carriageReturn < enterAt)
enterAt = whereToSearch.IndexOf('\r', startOfNumber);

if (endOfNumber == -1)
endOfNumber = whereToSearch.Length;

for (int i = startOfNumber; i < endOfNumber; i++)
for(int i = startOfNumber; i < whereToSearch.Length; i++)
{
bool found = false;
for (int indexInArray = 0; indexInArray < sValidNumericalChars.Length; indexInArray++)
if (!sValidNumericalChars.Contains(whereToSearch[i]))
{
if (whereToSearch[i] == sValidNumericalChars[indexInArray])
{
found = true;
break;
}
break;
}

if (!found)
else
{
// if we got here, then the character is not valid, so end the string
endOfNumber = i;
break;
endOfNumber = i+1;
}
}

if(endOfNumber != startOfNumber)
{
substring = whereToSearch.Substring(startOfNumber,
endOfNumber - startOfNumber);

// this method is called when reading from a file.
// usually, files use the . rather than other numerical formats, so if this fails, just use the regular . format
int toReturn = int.Parse(substring);
return toReturn;
}
}
}
catch (System.FormatException)
{
return int.Parse(substring, System.Globalization.NumberFormatInfo.InvariantInfo);
}
return 0;
}

public static int GetIntAfter(string stringToSearchFor, string whereToSearch, ref int startIndex)
{
int startOfNumber = -1;
int endOfNumber = -1;
string substring = string.Empty;

if (endOfNumber == -1 || (enterAt != -1 && enterAt < endOfNumber))
endOfNumber = enterAt;
if (endOfNumber == -1)
endOfNumber = whereToSearch.Length;
try
{
int indexOf = whereToSearch.IndexOf(stringToSearchFor, startIndex);

substring = whereToSearch.Substring(startOfNumber,
endOfNumber - startOfNumber);
if (indexOf != -1)
{
startOfNumber = indexOf + stringToSearchFor.Length;
endOfNumber = startIndex;

// this method is called when reading from a file.
// usually, files use the . rather than other numerical formats, so if this fails, just use the regular . format
int toReturn = int.Parse(substring);
return toReturn;
startIndex = startOfNumber;
for (int i = startOfNumber; i < whereToSearch.Length; i++)
{
startIndex = i + 1;
if (!sValidNumericalChars.Contains(whereToSearch[i]))
{
break;
}
else
{
endOfNumber = i + 1;
}
}

if (endOfNumber > startOfNumber)
{
substring = whereToSearch.Substring(startOfNumber,
endOfNumber - startOfNumber);

// this method is called when reading from a file.
// usually, files use the . rather than other numerical formats, so if this fails, just use the regular . format
int toReturn = int.Parse(substring);
return toReturn;
}
}
}
catch (System.FormatException)
{
return int.Parse(substring, System.Globalization.NumberFormatInfo.InvariantInfo);

}

return 0;

}

static char[] WhitespaceChars = new char[] { ' ', '\n', '\t', '\r' };
Expand Down

0 comments on commit 5fafb08

Please sign in to comment.