From 516265bf5bc9379e543f4260fc3c5466b8256088 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Wed, 28 Jul 2021 17:22:47 +0200 Subject: [PATCH] Fixed GenericFont's SplitString using incorrect width for special characters and improved documentation --- CHANGELOG.md | 1 + MLEM.Extended/Font/GenericBitmapFont.cs | 4 +- MLEM.Extended/Font/GenericStashFont.cs | 4 +- MLEM/Font/GenericFont.cs | 54 ++++++++++++++++--------- MLEM/Font/GenericSpriteFont.cs | 4 +- 5 files changed, 42 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3883e6..d672dad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ Improvements Fixes - Set default values for InputHandler held and pressed keys to avoid an exception if buttons are held in the very first frame +- Fixed GenericFont MeasureString using incorrect width for Zwsp and OneEmSpace ### MLEM.Ui Additions diff --git a/MLEM.Extended/Font/GenericBitmapFont.cs b/MLEM.Extended/Font/GenericBitmapFont.cs index 7ac84cd..922f6e7 100644 --- a/MLEM.Extended/Font/GenericBitmapFont.cs +++ b/MLEM.Extended/Font/GenericBitmapFont.cs @@ -33,9 +33,9 @@ namespace MLEM.Extended.Font { } /// - protected override Vector2 MeasureChar(char c) { + protected override float MeasureChar(char c) { var region = this.Font.GetCharacterRegion(c); - return region != null ? new Vector2(region.XAdvance, region.Height) : Vector2.Zero; + return region != null ? new Vector2(region.XAdvance, region.Height).X : 0; } /// diff --git a/MLEM.Extended/Font/GenericStashFont.cs b/MLEM.Extended/Font/GenericStashFont.cs index f0cdc62..b3e6b1a 100644 --- a/MLEM.Extended/Font/GenericStashFont.cs +++ b/MLEM.Extended/Font/GenericStashFont.cs @@ -53,8 +53,8 @@ namespace MLEM.Extended.Font { } /// - protected override Vector2 MeasureChar(char c) { - return this.Font.MeasureString(c.ToCachedString()); + protected override float MeasureChar(char c) { + return this.Font.MeasureString(c.ToCachedString()).X; } private static float CalculateLineHeight(SpriteFontBase font) { diff --git a/MLEM/Font/GenericFont.cs b/MLEM/Font/GenericFont.cs index 17f0c6c..9d2c055 100644 --- a/MLEM/Font/GenericFont.cs +++ b/MLEM/Font/GenericFont.cs @@ -1,6 +1,7 @@ using System.Text; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; +using MLEM.Extensions; using MLEM.Misc; namespace MLEM.Font { @@ -37,11 +38,19 @@ namespace MLEM.Font { /// public abstract GenericFont Italic { get; } - /// + /// + /// The height of each line of text of this font. + /// This is the value that the text's draw position is offset by every time a newline character is reached. + /// public abstract float LineHeight { get; } - /// - protected abstract Vector2 MeasureChar(char c); + /// + /// 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 + protected abstract float MeasureChar(char c); /// public abstract void DrawString(SpriteBatch batch, string text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth); @@ -49,27 +58,34 @@ namespace MLEM.Font { /// public abstract void DrawString(SpriteBatch batch, StringBuilder text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth); - /// - public void DrawString(SpriteBatch batch, string text, Vector2 position, Color color) { - this.DrawString(batch, text, position, color, 0, Vector2.Zero, Vector2.One, SpriteEffects.None, 0); - } - /// public void DrawString(SpriteBatch batch, string text, Vector2 position, Color color, float rotation, Vector2 origin, float scale, SpriteEffects effects, float layerDepth) { this.DrawString(batch, text, position, color, rotation, origin, new Vector2(scale), effects, layerDepth); } - /// - public void DrawString(SpriteBatch batch, StringBuilder text, Vector2 position, Color color) { - this.DrawString(batch, text, position, color, 0, Vector2.Zero, Vector2.One, SpriteEffects.None, 0); - } - /// public void DrawString(SpriteBatch batch, StringBuilder text, Vector2 position, Color color, float rotation, Vector2 origin, float scale, SpriteEffects effects, float layerDepth) { this.DrawString(batch, text, position, color, rotation, origin, new Vector2(scale), effects, layerDepth); } - /// + /// + public void DrawString(SpriteBatch batch, string text, Vector2 position, Color color) { + this.DrawString(batch, text, position, color, 0, Vector2.Zero, Vector2.One, SpriteEffects.None, 0); + } + + /// + public void DrawString(SpriteBatch batch, StringBuilder text, Vector2 position, Color color) { + this.DrawString(batch, text, position, color, 0, Vector2.Zero, Vector2.One, SpriteEffects.None, 0); + } + + /// + /// Measures the width of the given string when drawn with this font's underlying font. + /// This method uses internally to calculate the size of known characters and calculates additional characters like , and . + /// If the text contains newline characters (\n), the size returned will represent a rectangle that encompasses the width of the longest line and the string's full height. + /// + /// The text whose size to calculate + /// 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) { var size = Vector2.Zero; if (text.Length <= 0) @@ -85,7 +101,7 @@ namespace MLEM.Font { xOffset += this.LineHeight; break; case Nbsp: - xOffset += this.MeasureChar(' ').X; + xOffset += this.MeasureChar(' '); break; case Zwsp: // don't add width for a zero-width space @@ -96,10 +112,10 @@ namespace MLEM.Font { i = text.Length - 1; break; } - xOffset += this.MeasureChar(' ').X; + xOffset += this.MeasureChar(' '); break; default: - xOffset += this.MeasureChar(text[i]).X; + xOffset += this.MeasureChar(text[i]); break; } // increase x size if this line is the longest @@ -164,9 +180,9 @@ namespace MLEM.Font { widthSinceLastSpace = 0; currWidth = 0; } else { - var cWidth = this.MeasureChar(c).X * scale; + var cWidth = this.MeasureString(c.ToCachedString()).X * scale; if (c == ' ' || c == OneEmSpace || c == Zwsp) { - // remember the location of this space + // remember the location of this (breaking!) space lastSpaceIndex = ret.Length; widthSinceLastSpace = 0; } else if (currWidth + cWidth >= width) { diff --git a/MLEM/Font/GenericSpriteFont.cs b/MLEM/Font/GenericSpriteFont.cs index d7b1a7f..7634796 100644 --- a/MLEM/Font/GenericSpriteFont.cs +++ b/MLEM/Font/GenericSpriteFont.cs @@ -33,8 +33,8 @@ namespace MLEM.Font { } /// - protected override Vector2 MeasureChar(char c) { - return this.Font.MeasureString(c.ToCachedString()); + protected override float MeasureChar(char c) { + return this.Font.MeasureString(c.ToCachedString()).X; } ///