From d5e5d1d5369c6e49cfc74ffb43d3ef8789b51079 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Sun, 23 Oct 2022 21:23:16 +0200 Subject: [PATCH] moved the new ConvertCachedUtf32 to CodePointSource --- MLEM.Extended/Font/GenericStashFont.cs | 2 +- MLEM/Extensions/CharExtensions.cs | 4 ++-- MLEM/Font/CodePointSource.cs | 19 +++++++++++++++++-- MLEM/Font/GenericFont.cs | 23 ++++------------------- MLEM/Font/GenericSpriteFont.cs | 2 +- MLEM/Formatting/TokenizedString.cs | 2 +- 6 files changed, 26 insertions(+), 26 deletions(-) diff --git a/MLEM.Extended/Font/GenericStashFont.cs b/MLEM.Extended/Font/GenericStashFont.cs index 0d2988b..a6f2b9e 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(this.ConvertCachedUtf32(codePoint)).X; + return this.Font.MeasureString(CodePointSource.ToString(codePoint)).X; } /// diff --git a/MLEM/Extensions/CharExtensions.cs b/MLEM/Extensions/CharExtensions.cs index 4b550b8..143c9f2 100644 --- a/MLEM/Extensions/CharExtensions.cs +++ b/MLEM/Extensions/CharExtensions.cs @@ -5,7 +5,7 @@ namespace MLEM.Extensions { /// /// A set of extensions for dealing with /// - [Obsolete("ToCachedString is deprecated. Consider using a more robust, custom implementation for text caching.")] + [Obsolete("ToCachedString is deprecated. Consider using a more robust, custom implementation for text caching, or CodePointSource.ToString for UTF-32 caching.")] public static class CharExtensions { private static readonly Dictionary Cache = new Dictionary(); @@ -16,7 +16,7 @@ namespace MLEM.Extensions { /// /// The character to turn into a string /// A string representing the character - [Obsolete("ToCachedString is deprecated. Consider using a more robust, custom implementation for text caching.")] + [Obsolete("ToCachedString is deprecated. Consider using a more robust, custom implementation for text caching, or CodePointSource.ToString for UTF-32 caching.")] public static string ToCachedString(this char c) { if (!CharExtensions.Cache.TryGetValue(c, out var ret)) { ret = c.ToString(); diff --git a/MLEM/Font/CodePointSource.cs b/MLEM/Font/CodePointSource.cs index 93be007..fe4e3d2 100644 --- a/MLEM/Font/CodePointSource.cs +++ b/MLEM/Font/CodePointSource.cs @@ -4,10 +4,12 @@ using System.Text; namespace MLEM.Font { /// - /// A code point source is a wrapper around a or that allows retrieving UTF-32 code points at a given index using . Additionally, it allows enumerating every code point in the underlying or . + /// A code point source is a wrapper around a or that allows retrieving UTF-32 code points at a given index using . Additionally, it allows enumerating every code point in the underlying or . This class also contains , which converts a code point into its representation, but caches the result to avoid allocating excess memory. /// public readonly struct CodePointSource : IEnumerable { + private static readonly Dictionary StringCache = new Dictionary(); + private readonly string strg; private readonly StringBuilder builder; private char this[int index] => this.strg?[index] ?? this.builder[index]; @@ -42,7 +44,7 @@ namespace MLEM.Font { /// /// The index at which to return the code point, which is measured in characters. /// Whether the represents a low surrogate. If this is , the represents a high surrogate and the low surrogate will be looked for in the following character. If this is , the represents a low surrogate and the high surrogate will be looked for in the previous character. - /// + /// The code point at the given location, as well as its length. public (int CodePoint, int Length) GetCodePoint(int index, bool indexLowSurrogate = false) { var curr = this[index]; if (indexLowSurrogate) { @@ -80,5 +82,18 @@ namespace MLEM.Font { return this.GetEnumerator(); } + /// + /// 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 static string ToString(int codePoint) { + if (!CodePointSource.StringCache.TryGetValue(codePoint, out var ret)) { + ret = char.ConvertFromUtf32(codePoint); + CodePointSource.StringCache.Add(codePoint, ret); + } + return ret; + } + } } diff --git a/MLEM/Font/GenericFont.cs b/MLEM/Font/GenericFont.cs index 5eaf081..2895a99 100644 --- a/MLEM/Font/GenericFont.cs +++ b/MLEM/Font/GenericFont.cs @@ -48,8 +48,6 @@ 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. @@ -175,19 +173,6 @@ 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) @@ -240,9 +225,9 @@ namespace MLEM.Font { var innerIndex = fromBack ? text.Length - 1 - index : index; var (codePoint, length) = text.GetCodePoint(innerIndex, fromBack); if (fromBack) { - total.Insert(0, this.ConvertCachedUtf32(codePoint)); + total.Insert(0, CodePointSource.ToString(codePoint)); } else { - total.Append(this.ConvertCachedUtf32(codePoint)); + total.Append(CodePointSource.ToString(codePoint)); } if (this.MeasureString(new CodePointSource(total + ellipsis), false, fontFunction).X * scale >= width) { @@ -273,7 +258,7 @@ namespace MLEM.Font { currWidth = 0; } else { var font = fontFunction?.Invoke(index) ?? this; - var character = this.ConvertCachedUtf32(codePoint); + var character = CodePointSource.ToString(codePoint); var charWidth = font.MeasureString(character).X * scale; if (codePoint == ' ' || codePoint == GenericFont.Emsp || codePoint == GenericFont.Zwsp) { // remember the location of this (breaking!) space @@ -349,7 +334,7 @@ namespace MLEM.Font { offset.X = 0; offset.Y += this.LineHeight; } else { - var character = this.ConvertCachedUtf32(codePoint); + var character = CodePointSource.ToString(codePoint); var charSize = this.MeasureString(character); var charPos = offset; diff --git a/MLEM/Font/GenericSpriteFont.cs b/MLEM/Font/GenericSpriteFont.cs index d038f4c..178a289 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(this.ConvertCachedUtf32(codePoint)).X; + return this.Font.MeasureString(CodePointSource.ToString(codePoint)).X; } /// diff --git a/MLEM/Formatting/TokenizedString.cs b/MLEM/Formatting/TokenizedString.cs index 918a59d..7dc3825 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 = drawFont.ConvertCachedUtf32(codePoint); + var character = CodePointSource.ToString(codePoint); if (indexInToken == 0) token.DrawSelf(time, batch, pos + innerOffset, drawFont, color, scale, depth);