diff --git a/MLEM.Extended/Font/GenericStashFont.cs b/MLEM.Extended/Font/GenericStashFont.cs
index b84e5e3..0d2988b 100644
--- a/MLEM.Extended/Font/GenericStashFont.cs
+++ b/MLEM.Extended/Font/GenericStashFont.cs
@@ -33,7 +33,7 @@ namespace MLEM.Extended.Font {
///
protected override float MeasureCharacter(int codePoint) {
- return this.Font.MeasureString(char.ConvertFromUtf32(codePoint)).X;
+ return this.Font.MeasureString(this.ConvertCachedUtf32(codePoint)).X;
}
///
diff --git a/MLEM/Font/GenericFont.cs b/MLEM/Font/GenericFont.cs
index 626d2d6..5eaf081 100644
--- a/MLEM/Font/GenericFont.cs
+++ b/MLEM/Font/GenericFont.cs
@@ -48,6 +48,8 @@ namespace MLEM.Font {
///
public abstract float LineHeight { get; }
+ private readonly Dictionary codePointCache = new Dictionary();
+
///
/// Measures the width of the given code point with the default scale for use in .
/// Note that this method does not support , and for most generic fonts, which is why should be used even for single characters.
@@ -173,6 +175,19 @@ namespace MLEM.Font {
return this.SplitStringSeparate(new CodePointSource(text), width, scale, null);
}
+ ///
+ /// Converts the given UTF-32 into a string using , but caches the result in a cache to avoid allocating excess memory.
+ ///
+ /// The UTF-32 code point to convert.
+ /// The string representation of the code point.
+ public string ConvertCachedUtf32(int codePoint) {
+ if (!this.codePointCache.TryGetValue(codePoint, out var ret)) {
+ ret = char.ConvertFromUtf32(codePoint);
+ this.codePointCache.Add(codePoint, ret);
+ }
+ return ret;
+ }
+
internal Vector2 MeasureString(CodePointSource text, bool ignoreTrailingSpaces, Func fontFunction) {
var size = Vector2.Zero;
if (text.Length <= 0)
@@ -225,9 +240,9 @@ namespace MLEM.Font {
var innerIndex = fromBack ? text.Length - 1 - index : index;
var (codePoint, length) = text.GetCodePoint(innerIndex, fromBack);
if (fromBack) {
- total.Insert(0, char.ConvertFromUtf32(codePoint));
+ total.Insert(0, this.ConvertCachedUtf32(codePoint));
} else {
- total.Append(char.ConvertFromUtf32(codePoint));
+ total.Append(this.ConvertCachedUtf32(codePoint));
}
if (this.MeasureString(new CodePointSource(total + ellipsis), false, fontFunction).X * scale >= width) {
@@ -258,7 +273,7 @@ namespace MLEM.Font {
currWidth = 0;
} else {
var font = fontFunction?.Invoke(index) ?? this;
- var character = char.ConvertFromUtf32(codePoint);
+ var character = this.ConvertCachedUtf32(codePoint);
var charWidth = font.MeasureString(character).X * scale;
if (codePoint == ' ' || codePoint == GenericFont.Emsp || codePoint == GenericFont.Zwsp) {
// remember the location of this (breaking!) space
@@ -334,7 +349,7 @@ namespace MLEM.Font {
offset.X = 0;
offset.Y += this.LineHeight;
} else {
- var character = char.ConvertFromUtf32(codePoint);
+ var character = this.ConvertCachedUtf32(codePoint);
var charSize = this.MeasureString(character);
var charPos = offset;
diff --git a/MLEM/Font/GenericSpriteFont.cs b/MLEM/Font/GenericSpriteFont.cs
index 7d50f7e..d038f4c 100644
--- a/MLEM/Font/GenericSpriteFont.cs
+++ b/MLEM/Font/GenericSpriteFont.cs
@@ -35,7 +35,7 @@ namespace MLEM.Font {
///
protected override float MeasureCharacter(int codePoint) {
- return this.Font.MeasureString(char.ConvertFromUtf32(codePoint)).X;
+ return this.Font.MeasureString(this.ConvertCachedUtf32(codePoint)).X;
}
///
diff --git a/MLEM/Formatting/TokenizedString.cs b/MLEM/Formatting/TokenizedString.cs
index c4b1a4e..918a59d 100644
--- a/MLEM/Formatting/TokenizedString.cs
+++ b/MLEM/Formatting/TokenizedString.cs
@@ -164,7 +164,7 @@ namespace MLEM.Formatting {
var line = new CodePointSource(token.SplitDisplayString[l]);
while (charIndex < line.Length) {
var (codePoint, length) = line.GetCodePoint(charIndex);
- var character = char.ConvertFromUtf32(codePoint);
+ var character = drawFont.ConvertCachedUtf32(codePoint);
if (indexInToken == 0)
token.DrawSelf(time, batch, pos + innerOffset, drawFont, color, scale, depth);