private void Update() { if (!_dirty) { return; } if (string.IsNullOrEmpty(_text)) { _strings = new TextLine[0]; _dirty = false; return; } var lines = new List <TextLine>(); var i = 0; var line = new TextLine { TextStartIndex = i }; var width = Width; while (i < _text.Length) { var c = LayoutRow(i, width, true); if (i == c.StartIndex && c.CharsCount == 0) { break; } var chunk = new TextChunk(_font, _text.Substring(c.StartIndex, c.CharsCount), new Point(c.X, c.Y), CalculateGlyphs) { TextStartIndex = i, Color = c.Color }; width -= chunk.Size.X; i = c.StartIndex + c.CharsCount; line.Chunks.Add(chunk); line.Count += chunk.Count; line.Size.X += chunk.Size.X; if (chunk.Size.Y > line.Size.Y) { line.Size.Y = chunk.Size.Y; } if (c.LineEnd) { // New line lines.Add(line); line = new TextLine { TextStartIndex = i }; width = Width; } } _strings = lines.ToArray(); // Calculate size _size = Point.Zero; for (i = 0; i < _strings.Length; ++i) { line = _strings[i]; line.LineIndex = i; line.Top = _size.Y; for (var j = 0; j < line.Chunks.Count; ++j) { var chunk = line.Chunks[j]; chunk.LineIndex = line.LineIndex; chunk.ChunkIndex = j; chunk.Top = line.Top; } if (line.Size.X > _size.X) { _size.X = line.Size.X; } _size.Y += line.Size.Y; if (i < _strings.Length - 1) { _size.Y += _verticalSpacing; } } _dirty = false; }
public TextLine[] Format(SpriteFont font, string text, Options options) { if (string.IsNullOrEmpty(text)) { return(new TextLine[0]); } _font = font; var pt = ParseType.Text; // First run - gather lexemes _lexeme = new Lexeme(); _lexemes.Clear(); var str = new StringBuilder(); for (var pos = 0; pos < text.Length; ++pos) { var c = text[pos]; if (pt == ParseType.Text) { if (options.Color && c == '[' && pos < text.Length - 1 && text[pos + 1] != '[') { // Switch to color parsing StoreLexeme(); pt = ParseType.Color; } else if (c == '\n') { StoreLexeme(); // Add linebreak lexeme _lexeme.type = LexemeType.LineBreak; _lexeme.AppendChar(c, pos); StoreLexeme(); } else if (c == ' ' && _lexeme.type == LexemeType.Word) { StoreLexeme(); _lexeme.type = LexemeType.Space; _lexeme.AppendChar(c, pos); } else if (c == ' ') { _lexeme.AppendChar(c, pos); } else if (c > ' ') { if (_lexeme.type == LexemeType.Space) { StoreLexeme(); _lexeme.type = LexemeType.Word; } if (options.IsMenuText && c == '&') { _lexeme.UnderscoreIndex = _lexeme.chars.Count; } else { _lexeme.AppendChar(c, pos); } if (options.Color && c == '[') { // Means we have [[ // So one [ should be skipped ++pos; } } } else if (pt == ParseType.Color) { if (c != ']') { str.Append(c); } else if (str.Length >= 1) { var color = str.ToString().FromName(); str.Clear(); var l = new Lexeme { type = LexemeType.Color, color = color ?? Color.White }; _lexemes.Add(l); pt = ParseType.Text; } } } StoreLexeme(); // Second run - go through lexemes _result.Clear(); _lastLine = new TextLine(); _lastRun = new TextRun(_font, _currentColor); _fullString.Clear(); foreach (var li in _lexemes) { switch (li.type) { case LexemeType.LineBreak: StoreLine(); break; case LexemeType.Space: case LexemeType.Word: _fullString.Append(li.text); if (li.UnderscoreIndex != null) { _lastRun.UnderscoreIndex = _lastRun.Count + li.UnderscoreIndex; } if (options.Width.HasValue) { var sz = font.MeasureString(_fullString.ToString()); if (sz.X <= options.Width.Value) { _lastRun.Append(li.chars); } else { StoreLine(); if (li.type == LexemeType.Word) { _fullString.Append(li.text); _lastRun.Append(li.chars); } } } else { _lastRun.Append(li.chars); } break; case LexemeType.Color: _currentColor = li.color; StoreRun(); break; } } StoreLine(); return(_result.ToArray()); }