internal ChunkInfo LayoutRow(int startIndex, int?width, bool parseCommands) { var r = new ChunkInfo { StartIndex = startIndex, LineEnd = true }; if (string.IsNullOrEmpty(_text)) { return(r); } _stringBuilder.Clear(); int? lastBreakPosition = null; Point?lastBreakMeasure = null; for (var i = r.StartIndex; i < _text.Length; ++i) { var c = _text[i]; if (SupportsCommands && c == '\\') { if (i < _text.Length - 2 && _text[i + 1] == 'c' && _text[i + 2] == '[') { // Find end var startPos = i + 3; var j = _text.IndexOf(']', startPos); if (j != -1) { // Found if (i > r.StartIndex) { // Break right here, as next chunk has another color r.LineEnd = false; return(r); } if (parseCommands) { r.Color = ColorStorage.FromName(_text.Substring(startPos, j - startPos)); } r.StartIndex = j + 1; i = j; continue; } } } _stringBuilder.Append(c); var sz = Point.Zero; if (c != '\n') { var v = Font.MeasureString(_stringBuilder); sz = new Point((int)v.X, (int)v.Y); } else { sz = new Point(r.X + NewLineWidth, Math.Max(r.Y, CrossEngineStuff.LineSpacing(_font))); // Break right here ++r.CharsCount; r.X = sz.X; r.Y = sz.Y; break; } if (width != null && sz.X > width.Value) { if (lastBreakPosition != null) { r.CharsCount = lastBreakPosition.Value - r.StartIndex; } if (lastBreakMeasure != null) { r.X = lastBreakMeasure.Value.X; r.Y = lastBreakMeasure.Value.Y; } break; } if (char.IsWhiteSpace(c)) { lastBreakPosition = i + 1; lastBreakMeasure = sz; } ++r.CharsCount; r.X = sz.X; r.Y = sz.Y; } return(r); }
internal ChunkInfo LayoutRow(int startIndex, int?width, bool parseCommands) { var r = new ChunkInfo { StartIndex = startIndex, LineEnd = true }; if (string.IsNullOrEmpty(_text)) { return(r); } _stringBuilder.Clear(); int? lastBreakPosition = null; Point?lastBreakMeasure = null; for (var i = r.StartIndex; i < _text.Length; ++i) { var c = _text[i]; if (char.IsHighSurrogate(c)) { _stringBuilder.Append(c); ++r.CharsCount; continue; } if (SupportsCommands && c == '\\') { if (i < _text.Length - 2) { char commandChar = _text[i + 1]; if (_text[i + 2] == '[') { // Find parameter end var parameterStartIndex = i + 3; var parameterEndIndex = _text.IndexOf(']', parameterStartIndex); if (parameterEndIndex != -1) { // Found if (i > r.StartIndex) { // Break right here, as next chunk is a command block if (commandChar == SpriteCommandChar) { // sprites have width, will this one fit on our line? if (width != null) { var spriteId = SpriteChunk.GetSpriteId(_text, parameterStartIndex, parameterEndIndex); var size = TrollskogIntegration.MeasureSprite(spriteId, _font); r.LineEnd = (r.X + size.X) > width.Value; } } else { r.LineEnd = false; } return(r); } if (parseCommands && commandChar == ColorCommandChar) { r.Color = ColorStorage.FromName(_text.Substring(parameterStartIndex, parameterEndIndex - parameterStartIndex)); } else if (commandChar == SpriteCommandChar) { // Break because this is a sprite chunk var spriteId = SpriteChunk.GetSpriteId(_text, parameterStartIndex, parameterEndIndex); var size = TrollskogIntegration.MeasureSprite(spriteId, _font); r.LineEnd = parameterEndIndex == _text.Length - 1; r.X = size.X; r.Y = size.Y; r.SpriteId = spriteId; r.CharsCount = parameterEndIndex - r.StartIndex + 1; return(r); } } r.StartIndex = parameterEndIndex + 1; i = parameterEndIndex; continue; } if (commandChar == NewlineCommandChar) { Point sz2 = new(r.X + NewLineWidth, Math.Max(r.Y, _font.FontSize)); // Break right here, consuming 2 chars '\\' and 'n' r.SkipChars = 2; r.CharsCount += 2; r.LineEnd = true; r.X = sz2.X; r.Y = sz2.Y; break; } } } _stringBuilder.Append(c); Point sz; if (c != '\n') { var v = Font.MeasureString(_stringBuilder); sz = new Point((int)v.X, _font.FontSize); } else { sz = new Point(r.X + NewLineWidth, Math.Max(r.Y, _font.FontSize)); // Break right here ++r.CharsCount; r.X = sz.X; r.Y = sz.Y; break; } if (width != null && sz.X > width.Value) { if (lastBreakPosition != null) { r.CharsCount = lastBreakPosition.Value - r.StartIndex; } if (lastBreakMeasure != null) { r.X = lastBreakMeasure.Value.X; r.Y = lastBreakMeasure.Value.Y; } break; } if (char.IsWhiteSpace(c)) { lastBreakPosition = i + 1; lastBreakMeasure = sz; } ++r.CharsCount; r.X = sz.X; r.Y = sz.Y; } return(r); }