1
0
Fork 0
mirror of https://github.com/Ellpeck/MLEM.git synced 2024-05-09 19:18:44 +02:00

Cache TokenizedString inner offsets for non-Left text alignments

This commit is contained in:
Ell 2021-10-04 23:57:58 +02:00
parent f021215066
commit 9743c05e1a
3 changed files with 37 additions and 34 deletions

View file

@ -8,6 +8,9 @@ Jump to version:
## 5.2.0 (Unreleased)
### MLEM.Ui
Improvements
- Cache TokenizedString inner offsets for non-Left text alignments to improve performance
Fixes
- Fixed VerticalSpace height parameter being an integer

View file

@ -42,6 +42,7 @@ namespace MLEM.Formatting {
public readonly string RawSubstring;
internal RectangleF[] Area;
internal string ModifiedSubstring;
internal float[] InnerOffsets;
internal Token(Code[] appliedCodes, int index, int rawIndex, string substring, string rawSubstring) {
this.AppliedCodes = appliedCodes;

View file

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@ -37,6 +38,7 @@ namespace MLEM.Formatting {
/// </summary>
public readonly Code[] AllCodes;
private string modifiedString;
private float initialInnerOffset;
internal TokenizedString(GenericFont font, TextAlignment alignment, string rawString, string strg, Token[] tokens) {
this.RawString = rawString;
@ -111,7 +113,7 @@ namespace MLEM.Formatting {
/// <inheritdoc cref="GenericFont.DrawString(SpriteBatch,string,Vector2,Color,float,Vector2,float,SpriteEffects,float)"/>
public void Draw(GameTime time, SpriteBatch batch, Vector2 pos, GenericFont font, Color color, float scale, float depth, TextAlignment alignment = TextAlignment.Left) {
var innerOffset = new Vector2(this.GetInnerOffsetX(font, 0, 0, scale, alignment), 0);
var innerOffset = new Vector2(this.initialInnerOffset * scale, 0);
for (var t = 0; t < this.Tokens.Length; t++) {
var token = this.Tokens[t];
var drawFont = token.GetFont(font) ?? font;
@ -129,7 +131,7 @@ namespace MLEM.Formatting {
}
// only split at a new line, not between tokens!
if (l < token.SplitDisplayString.Length - 1) {
innerOffset.X = this.GetInnerOffsetX(font, t, l + 1, scale, alignment);
innerOffset.X = token.InnerOffsets[l] * scale;
innerOffset.Y += font.LineHeight * scale;
}
}
@ -172,45 +174,17 @@ namespace MLEM.Formatting {
this.RecalculateTokenData(font, alignment);
}
private float GetInnerOffsetX(GenericFont font, int tokenIndex, int lineIndex, float scale, TextAlignment alignment) {
if (alignment > TextAlignment.Left) {
var rest = this.GetRestOfLineLength(font, tokenIndex, lineIndex) * scale;
if (alignment == TextAlignment.Center)
rest /= 2;
return -rest;
}
return 0;
}
private float GetRestOfLineLength(GenericFont font, int tokenIndex, int lineIndex) {
var token = this.Tokens[tokenIndex];
var ret = font.MeasureString(token.SplitDisplayString[lineIndex], true).X;
if (lineIndex >= token.SplitDisplayString.Length - 1) {
// the line ends somewhere in or after the next token
for (var i = tokenIndex + 1; i < this.Tokens.Length; i++) {
var other = this.Tokens[i];
if (other.SplitDisplayString.Length > 1) {
// the line ends in this token
ret += font.MeasureString(other.SplitDisplayString[0]).X;
break;
} else {
// the line doesn't end in this token, so add it fully
ret += font.MeasureString(other.DisplayString).X;
}
}
}
return ret;
}
private void RecalculateTokenData(GenericFont font, TextAlignment alignment) {
// split display strings
foreach (var token in this.Tokens)
token.SplitDisplayString = token.DisplayString.Split('\n');
// token areas
var innerOffset = new Vector2(this.GetInnerOffsetX(font, 0, 0, 1, alignment), 0);
this.initialInnerOffset = this.GetInnerOffsetX(font, 0, 0, alignment);
var innerOffset = new Vector2(this.initialInnerOffset, 0);
for (var t = 0; t < this.Tokens.Length; t++) {
var token = this.Tokens[t];
token.InnerOffsets = new float[token.SplitDisplayString.Length - 1];
var area = new List<RectangleF>();
for (var l = 0; l < token.SplitDisplayString.Length; l++) {
var size = font.MeasureString(token.SplitDisplayString[l]);
@ -219,7 +193,7 @@ namespace MLEM.Formatting {
area.Add(rect);
if (l < token.SplitDisplayString.Length - 1) {
innerOffset.X = this.GetInnerOffsetX(font, t, l + 1, 1, alignment);
innerOffset.X = token.InnerOffsets[l] = this.GetInnerOffsetX(font, t, l + 1, alignment);
innerOffset.Y += font.LineHeight;
} else {
innerOffset.X += size.X;
@ -229,5 +203,30 @@ namespace MLEM.Formatting {
}
}
private float GetInnerOffsetX(GenericFont font, int tokenIndex, int lineIndex, TextAlignment alignment) {
if (alignment > TextAlignment.Left) {
var token = this.Tokens[tokenIndex];
var restOfLine = font.MeasureString(token.SplitDisplayString[lineIndex], true).X;
if (lineIndex >= token.SplitDisplayString.Length - 1) {
// the line ends somewhere in or after the next token
for (var i = tokenIndex + 1; i < this.Tokens.Length; i++) {
var other = this.Tokens[i];
if (other.SplitDisplayString.Length > 1) {
// the line ends in this token
restOfLine += font.MeasureString(other.SplitDisplayString[0]).X;
break;
} else {
// the line doesn't end in this token, so add it fully
restOfLine += font.MeasureString(other.DisplayString).X;
}
}
}
if (alignment == TextAlignment.Center)
restOfLine /= 2;
return -restOfLine;
}
return 0;
}
}
}