Fix rendering bug when splitting lines

The bug might occur if there are wide characters such as emojis
at the end of a line. The SplitLines method mixed cell width
and text length, which might give incorrect results. This commit
makes sure that comparison and calculation is done using cell width
where it's appropriate.
This commit is contained in:
Patrik Svensson
2020-10-24 01:45:41 +02:00
parent 041bd016a2
commit c9c0ad733f
11 changed files with 197 additions and 57 deletions

View File

@ -66,7 +66,7 @@ namespace Spectre.Console
}
var child = _child.Render(context, maxWidth - paddingWidth);
foreach (var (_, _, _, line) in Segment.SplitLines(child).Enumerate())
foreach (var (_, _, _, line) in Segment.SplitLines(context, child).Enumerate())
{
// Left padding
if (Padding.Left != 0)
@ -83,7 +83,7 @@ namespace Spectre.Console
}
// Missing space on right side?
var lineWidth = line.CellWidth(context);
var lineWidth = line.CellCount(context);
var diff = width - lineWidth - Padding.Left - Padding.Right;
if (diff > 0)
{

View File

@ -94,7 +94,7 @@ namespace Spectre.Console
// Split the child segments into lines.
var childSegments = ((IRenderable)child).Render(context, childWidth);
foreach (var line in Segment.SplitLines(childSegments, childWidth))
foreach (var line in Segment.SplitLines(context, childSegments, childWidth))
{
if (line.Count == 1 && line[0].IsWhiteSpace)
{
@ -109,7 +109,7 @@ namespace Spectre.Console
content.AddRange(line);
// Do we need to pad the panel?
var length = line.Sum(segment => segment.CellLength(context));
var length = line.Sum(segment => segment.CellCount(context));
if (length < childWidth)
{
var diff = childWidth - length;
@ -148,7 +148,7 @@ namespace Spectre.Console
var headerWidth = panelWidth - (EdgeWidth * 2);
var header = Segment.TruncateWithEllipsis(Header.Text, Header.Style ?? borderStyle, context, headerWidth);
var excessWidth = headerWidth - header.CellLength(context);
var excessWidth = headerWidth - header.CellCount(context);
if (excessWidth > 0)
{
switch (Header.Alignment ?? Justify.Left)

View File

@ -119,8 +119,8 @@ namespace Spectre.Console
return new Measurement(0, 0);
}
var min = _lines.Max(line => line.Max(segment => segment.CellLength(context)));
var max = _lines.Max(x => x.CellWidth(context));
var min = _lines.Max(line => line.Max(segment => segment.CellCount(context)));
var max = _lines.Max(x => x.CellCount(context));
return new Measurement(min, Math.Min(max, maxWidth));
}
@ -187,7 +187,7 @@ namespace Spectre.Console
return new List<SegmentLine>();
}
if (_lines.Max(x => x.CellWidth(context)) <= maxWidth)
if (_lines.Max(x => x.CellCount(context)) <= maxWidth)
{
return Clone();
}
@ -231,7 +231,7 @@ namespace Spectre.Console
continue;
}
var length = current.CellLength(context);
var length = current.CellCount(context);
if (length > maxWidth)
{
// The current segment is longer than the width of the console,
@ -239,7 +239,7 @@ namespace Spectre.Console
var segments = Segment.SplitOverflow(current, Overflow, context, maxWidth);
if (segments.Count > 0)
{
if (line.CellWidth(context) + segments[0].CellLength(context) > maxWidth)
if (line.CellCount(context) + segments[0].CellCount(context) > maxWidth)
{
lines.Add(line);
line = new SegmentLine();
@ -259,7 +259,7 @@ namespace Spectre.Console
}
else
{
if (line.CellWidth(context) + length > maxWidth)
if (line.CellCount(context) + length > maxWidth)
{
line.Add(Segment.Empty);
lines.Add(line);

View File

@ -52,7 +52,7 @@ namespace Spectre.Console
// Get the title and make sure it fits.
var title = GetTitleSegments(context, Title, maxWidth - 6);
if (Segment.CellLength(context, title) > maxWidth - 6)
if (Segment.CellCount(context, title) > maxWidth - 6)
{
// Truncate the title
title = Segment.TruncateWithEllipsis(title, context, maxWidth - 6);
@ -88,13 +88,13 @@ namespace Spectre.Console
{
var alignment = Alignment ?? Justify.Center;
var titleLength = Segment.CellLength(context, title);
var titleLength = Segment.CellCount(context, title);
if (alignment == Justify.Left)
{
var left = new Segment(new string('─', 2) + " ", Style ?? Style.Plain);
var rightLength = maxWidth - titleLength - left.CellLength(context) - 1;
var rightLength = maxWidth - titleLength - left.CellCount(context) - 1;
var right = new Segment(" " + new string('─', rightLength), Style ?? Style.Plain);
return (left, right);
@ -104,7 +104,7 @@ namespace Spectre.Console
var leftLength = ((maxWidth - titleLength) / 2) - 1;
var left = new Segment(new string('─', leftLength) + " ", Style ?? Style.Plain);
var rightLength = maxWidth - titleLength - left.CellLength(context) - 1;
var rightLength = maxWidth - titleLength - left.CellCount(context) - 1;
var right = new Segment(" " + new string('─', rightLength), Style ?? Style.Plain);
return (left, right);
@ -113,7 +113,7 @@ namespace Spectre.Console
{
var right = new Segment(" " + new string('─', 2), Style ?? Style.Plain);
var leftLength = maxWidth - titleLength - right.CellLength(context) - 1;
var leftLength = maxWidth - titleLength - right.CellCount(context) - 1;
var left = new Segment(new string('─', leftLength) + " ", Style ?? Style.Plain);
return (left, right);

View File

@ -217,7 +217,7 @@ namespace Spectre.Console
var justification = _columns[columnIndex].Alignment;
var childContext = context.WithJustification(justification);
var lines = Segment.SplitLines(cell.Render(childContext, rowWidth));
var lines = Segment.SplitLines(context, cell.Render(childContext, rowWidth));
cellHeight = Math.Max(cellHeight, lines.Count);
cells.Add(lines);
}
@ -261,7 +261,7 @@ namespace Spectre.Console
rowResult.AddRange(cell[cellRowIndex]);
// Pad cell content right
var length = cell[cellRowIndex].Sum(segment => segment.CellLength(context));
var length = cell[cellRowIndex].Sum(segment => segment.CellCount(context));
if (length < columnWidths[cellIndex])
{
rowResult.Add(new Segment(new string(' ', columnWidths[cellIndex] - length)));
@ -295,7 +295,7 @@ namespace Spectre.Console
Aligner.Align(context, rowResult, Alignment, actualMaxWidth);
// Is the row larger than the allowed max width?
if (Segment.CellLength(context, rowResult) > actualMaxWidth)
if (Segment.CellCount(context, rowResult) > actualMaxWidth)
{
result.AddRange(Segment.Truncate(context, rowResult, actualMaxWidth));
}