mirror of
https://github.com/Ellpeck/MLEM.git
synced 2024-11-26 06:28:35 +01:00
Cache TokenizedString inner offsets for non-Left text alignments
This commit is contained in:
parent
f021215066
commit
9743c05e1a
3 changed files with 37 additions and 34 deletions
|
@ -8,6 +8,9 @@ Jump to version:
|
||||||
|
|
||||||
## 5.2.0 (Unreleased)
|
## 5.2.0 (Unreleased)
|
||||||
### MLEM.Ui
|
### MLEM.Ui
|
||||||
|
Improvements
|
||||||
|
- Cache TokenizedString inner offsets for non-Left text alignments to improve performance
|
||||||
|
|
||||||
Fixes
|
Fixes
|
||||||
- Fixed VerticalSpace height parameter being an integer
|
- Fixed VerticalSpace height parameter being an integer
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ namespace MLEM.Formatting {
|
||||||
public readonly string RawSubstring;
|
public readonly string RawSubstring;
|
||||||
internal RectangleF[] Area;
|
internal RectangleF[] Area;
|
||||||
internal string ModifiedSubstring;
|
internal string ModifiedSubstring;
|
||||||
|
internal float[] InnerOffsets;
|
||||||
|
|
||||||
internal Token(Code[] appliedCodes, int index, int rawIndex, string substring, string rawSubstring) {
|
internal Token(Code[] appliedCodes, int index, int rawIndex, string substring, string rawSubstring) {
|
||||||
this.AppliedCodes = appliedCodes;
|
this.AppliedCodes = appliedCodes;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
@ -37,6 +38,7 @@ namespace MLEM.Formatting {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly Code[] AllCodes;
|
public readonly Code[] AllCodes;
|
||||||
private string modifiedString;
|
private string modifiedString;
|
||||||
|
private float initialInnerOffset;
|
||||||
|
|
||||||
internal TokenizedString(GenericFont font, TextAlignment alignment, string rawString, string strg, Token[] tokens) {
|
internal TokenizedString(GenericFont font, TextAlignment alignment, string rawString, string strg, Token[] tokens) {
|
||||||
this.RawString = rawString;
|
this.RawString = rawString;
|
||||||
|
@ -111,7 +113,7 @@ namespace MLEM.Formatting {
|
||||||
|
|
||||||
/// <inheritdoc cref="GenericFont.DrawString(SpriteBatch,string,Vector2,Color,float,Vector2,float,SpriteEffects,float)"/>
|
/// <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) {
|
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++) {
|
for (var t = 0; t < this.Tokens.Length; t++) {
|
||||||
var token = this.Tokens[t];
|
var token = this.Tokens[t];
|
||||||
var drawFont = token.GetFont(font) ?? font;
|
var drawFont = token.GetFont(font) ?? font;
|
||||||
|
@ -129,7 +131,7 @@ namespace MLEM.Formatting {
|
||||||
}
|
}
|
||||||
// only split at a new line, not between tokens!
|
// only split at a new line, not between tokens!
|
||||||
if (l < token.SplitDisplayString.Length - 1) {
|
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;
|
innerOffset.Y += font.LineHeight * scale;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,45 +174,17 @@ namespace MLEM.Formatting {
|
||||||
this.RecalculateTokenData(font, alignment);
|
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) {
|
private void RecalculateTokenData(GenericFont font, TextAlignment alignment) {
|
||||||
// split display strings
|
// split display strings
|
||||||
foreach (var token in this.Tokens)
|
foreach (var token in this.Tokens)
|
||||||
token.SplitDisplayString = token.DisplayString.Split('\n');
|
token.SplitDisplayString = token.DisplayString.Split('\n');
|
||||||
|
|
||||||
// token areas
|
// 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++) {
|
for (var t = 0; t < this.Tokens.Length; t++) {
|
||||||
var token = this.Tokens[t];
|
var token = this.Tokens[t];
|
||||||
|
token.InnerOffsets = new float[token.SplitDisplayString.Length - 1];
|
||||||
var area = new List<RectangleF>();
|
var area = new List<RectangleF>();
|
||||||
for (var l = 0; l < token.SplitDisplayString.Length; l++) {
|
for (var l = 0; l < token.SplitDisplayString.Length; l++) {
|
||||||
var size = font.MeasureString(token.SplitDisplayString[l]);
|
var size = font.MeasureString(token.SplitDisplayString[l]);
|
||||||
|
@ -219,7 +193,7 @@ namespace MLEM.Formatting {
|
||||||
area.Add(rect);
|
area.Add(rect);
|
||||||
|
|
||||||
if (l < token.SplitDisplayString.Length - 1) {
|
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;
|
innerOffset.Y += font.LineHeight;
|
||||||
} else {
|
} else {
|
||||||
innerOffset.X += size.X;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue