From a11a63c067be0ba6f58950c1796c5b58f90d27c5 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Sun, 28 Nov 2021 00:28:17 +0100 Subject: [PATCH] some GenericFont code style improvements --- MLEM/Font/GenericFont.cs | 43 +++++++++++++----------------- MLEM/Formatting/TokenizedString.cs | 8 +++--- 2 files changed, 22 insertions(+), 29 deletions(-) diff --git a/MLEM/Font/GenericFont.cs b/MLEM/Font/GenericFont.cs index bce5f7e..e0f634f 100644 --- a/MLEM/Font/GenericFont.cs +++ b/MLEM/Font/GenericFont.cs @@ -16,17 +16,17 @@ namespace MLEM.Font { /// /// This field holds the unicode representation of a one em space. /// This is a character that isn't drawn, but has the same width as . - /// Whereas a regular would have to explicitly support this character for width calculations, generic fonts implicitly support it in . + /// Whereas a regular would have to explicitly support this character for width calculations, generic fonts implicitly support it in . /// public const char OneEmSpace = '\u2003'; /// /// This field holds the unicode representation of a non-breaking space. - /// Whereas a regular would have to explicitly support this character for width calculations, generic fonts implicitly support it in . + /// Whereas a regular would have to explicitly support this character for width calculations, generic fonts implicitly support it in . /// public const char Nbsp = '\u00A0'; /// /// This field holds the unicode representation of a zero-width space. - /// Whereas a regular would have to explicitly support this character for width calculations and string splitting, generic fonts implicitly support it in and . + /// Whereas a regular would have to explicitly support this character for width calculations and string splitting, generic fonts implicitly support it in and . /// public const char Zwsp = '\u200B'; @@ -46,18 +46,9 @@ namespace MLEM.Font { /// public abstract float LineHeight { get; } - private readonly Func identity; - /// - /// Creates a new generic font with the default settings - /// - public GenericFont() { - this.identity = i => this; - } - - /// - /// Measures the width of the given character 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. + /// Measures the width of the given character 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. /// /// The character whose width to calculate /// The width of the given character with the default scale @@ -98,7 +89,7 @@ namespace MLEM.Font { /// Whether trailing whitespace should be ignored in the returned size, causing the end of each line to be effectively trimmed /// The size of the string when drawn with this font public Vector2 MeasureString(string text, bool ignoreTrailingSpaces = false) { - return MeasureString(this.identity, text, ignoreTrailingSpaces); + return this.MeasureString(text, ignoreTrailingSpaces, null); } /// @@ -112,13 +103,13 @@ namespace MLEM.Font { /// The characters to add to the end of the string if it is too long /// The truncated string, or the same string if it is shorter than the maximum width public string TruncateString(string text, float width, float scale, bool fromBack = false, string ellipsis = "") { - return TruncateString(this.identity, text, width, scale, fromBack, ellipsis); + return this.TruncateString(text, width, scale, fromBack, ellipsis, null); } /// /// Splits a string to a given maximum width, adding newline characters between each line. /// Also splits long words and supports zero-width spaces and takes into account existing newline characters in the passed . - /// See for a method that differentiates between existing newline characters and splits due to maximum width. + /// See for a method that differentiates between existing newline characters and splits due to maximum width. /// /// The text to split into multiple lines /// The maximum width that each line should have @@ -138,16 +129,16 @@ namespace MLEM.Font { /// The scale to use for width measurements /// The split string as an enumerable of split sections public IEnumerable SplitStringSeparate(string text, float width, float scale) { - return SplitStringSeparate(this.identity, text, width, scale); + return this.SplitStringSeparate(text, width, scale, null); } - internal static Vector2 MeasureString(Func fontFunction, string text, bool ignoreTrailingSpaces) { + internal Vector2 MeasureString(string text, bool ignoreTrailingSpaces, Func fontFunction) { var size = Vector2.Zero; if (text.Length <= 0) return size; var xOffset = 0F; for (var i = 0; i < text.Length; i++) { - var font = fontFunction(i); + var font = fontFunction?.Invoke(i) ?? this; switch (text[i]) { case '\n': xOffset = 0; @@ -179,11 +170,11 @@ namespace MLEM.Font { size.X = xOffset; } // include the last line's height too! - size.Y += fontFunction(text.Length - 1).LineHeight; + size.Y += (fontFunction?.Invoke(text.Length - 1) ?? this).LineHeight; return size; } - internal static string TruncateString(Func fontFunction, string text, float width, float scale, bool fromBack, string ellipsis) { + internal string TruncateString(string text, float width, float scale, bool fromBack, string ellipsis, Func fontFunction) { var total = new StringBuilder(); for (var i = 0; i < text.Length; i++) { if (fromBack) { @@ -192,7 +183,8 @@ namespace MLEM.Font { total.Append(text[i]); } - if (fontFunction(i).MeasureString(total + ellipsis).X * scale >= width) { + var font = fontFunction?.Invoke(i) ?? this; + if (font.MeasureString(total + ellipsis).X * scale >= width) { if (fromBack) { return total.Remove(0, 1).Insert(0, ellipsis).ToString(); } else { @@ -203,7 +195,7 @@ namespace MLEM.Font { return total.ToString(); } - internal static IEnumerable SplitStringSeparate(Func fontFunction, string text, float width, float scale) { + internal IEnumerable SplitStringSeparate(string text, float width, float scale, Func fontFunction) { var currWidth = 0F; var lastSpaceIndex = -1; var widthSinceLastSpace = 0F; @@ -217,7 +209,8 @@ namespace MLEM.Font { widthSinceLastSpace = 0; currWidth = 0; } else { - var cWidth = fontFunction(i).MeasureString(c.ToCachedString()).X * scale; + var font = fontFunction?.Invoke(i) ?? this; + var cWidth = font.MeasureString(c.ToCachedString()).X * scale; if (c == ' ' || c == OneEmSpace || c == Zwsp) { // remember the location of this (breaking!) space lastSpaceIndex = curr.Length; diff --git a/MLEM/Formatting/TokenizedString.cs b/MLEM/Formatting/TokenizedString.cs index d1ac51b..9382f0f 100644 --- a/MLEM/Formatting/TokenizedString.cs +++ b/MLEM/Formatting/TokenizedString.cs @@ -59,14 +59,14 @@ namespace MLEM.Formatting { /// The text alignment that should be used for width calculations public void Split(GenericFont font, float width, float scale, TextAlignment alignment = TextAlignment.Left) { // a split string has the same character count as the input string but with newline characters added - this.modifiedString = string.Join("\n", GenericFont.SplitStringSeparate(i => this.GetFontForIndex(font, i), this.String, width, scale)); + this.modifiedString = string.Join("\n", font.SplitStringSeparate(this.String, width, scale, i => this.GetFontForIndex(font, i))); this.StoreModifiedSubstrings(font, alignment); } /// /// Truncates this tokenized string, removing any additional characters that exceed the length from the displayed string. /// Note that a tokenized string can be re-truncated without losing any of its actual data, as this operation merely modifies the . - /// + /// /// /// The font to use for width calculations /// The maximum width, in display pixels based on the font and scale @@ -74,13 +74,13 @@ namespace MLEM.Formatting { /// The characters to add to the end of the string if it is too long /// The text alignment that should be used for width calculations public void Truncate(GenericFont font, float width, float scale, string ellipsis = "", TextAlignment alignment = TextAlignment.Left) { - this.modifiedString = GenericFont.TruncateString(i => this.GetFontForIndex(font, i), this.String, width, scale, false, ellipsis); + this.modifiedString = font.TruncateString(this.String, width, scale, false, ellipsis, i => this.GetFontForIndex(font, i)); this.StoreModifiedSubstrings(font, alignment); } /// public Vector2 Measure(GenericFont font) { - return GenericFont.MeasureString(i => this.GetFontForIndex(font, i), this.DisplayString, false); + return font.MeasureString(this.DisplayString, false, i => this.GetFontForIndex(font, i)); } ///