mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2026-01-02 01:03:29 +01:00
Fix Cell.CombiningMarks property getter rune list allocation (#3980)
* Skip rune list allocation from accessing Cell.CombiningMarks property The getter would every time allocate a new list when the backing field was not assigned, which is most of the time. * Fix comment about performance I accidentally word. Is this dangerous?
This commit is contained in:
@@ -217,7 +217,7 @@ public abstract class ConsoleDriver : IConsoleDriver
|
|||||||
if (Contents [Row, Col - 1].CombiningMarks.Count > 0)
|
if (Contents [Row, Col - 1].CombiningMarks.Count > 0)
|
||||||
{
|
{
|
||||||
// Just add this mark to the list
|
// Just add this mark to the list
|
||||||
Contents [Row, Col - 1].CombiningMarks.Add (rune);
|
Contents [Row, Col - 1].AddCombiningMark (rune);
|
||||||
|
|
||||||
// Ignore. Don't move to next column (let the driver figure out what to do).
|
// Ignore. Don't move to next column (let the driver figure out what to do).
|
||||||
}
|
}
|
||||||
@@ -240,7 +240,7 @@ public abstract class ConsoleDriver : IConsoleDriver
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// It didn't normalize. Add it to the Cell to left's CM list
|
// It didn't normalize. Add it to the Cell to left's CM list
|
||||||
Contents [Row, Col - 1].CombiningMarks.Add (rune);
|
Contents [Row, Col - 1].AddCombiningMark (rune);
|
||||||
|
|
||||||
// Ignore. Don't move to next column (let the driver figure out what to do).
|
// Ignore. Don't move to next column (let the driver figure out what to do).
|
||||||
}
|
}
|
||||||
@@ -298,7 +298,7 @@ public abstract class ConsoleDriver : IConsoleDriver
|
|||||||
else if (!Clip.Contains (Col, Row))
|
else if (!Clip.Contains (Col, Row))
|
||||||
{
|
{
|
||||||
// Our 1st column is outside the clip, so we can't display a wide character.
|
// Our 1st column is outside the clip, so we can't display a wide character.
|
||||||
Contents [Row, Col+1].Rune = Rune.ReplacementChar;
|
Contents [Row, Col + 1].Rune = Rune.ReplacementChar;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ public class OutputBuffer : IOutputBuffer
|
|||||||
if (Contents [Row, Col - 1].CombiningMarks.Count > 0)
|
if (Contents [Row, Col - 1].CombiningMarks.Count > 0)
|
||||||
{
|
{
|
||||||
// Just add this mark to the list
|
// Just add this mark to the list
|
||||||
Contents [Row, Col - 1].CombiningMarks.Add (rune);
|
Contents [Row, Col - 1].AddCombiningMark (rune);
|
||||||
|
|
||||||
// Ignore. Don't move to next column (let the driver figure out what to do).
|
// Ignore. Don't move to next column (let the driver figure out what to do).
|
||||||
}
|
}
|
||||||
@@ -187,7 +187,7 @@ public class OutputBuffer : IOutputBuffer
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// It didn't normalize. Add it to the Cell to left's CM list
|
// It didn't normalize. Add it to the Cell to left's CM list
|
||||||
Contents [Row, Col - 1].CombiningMarks.Add (rune);
|
Contents [Row, Col - 1].AddCombiningMark (rune);
|
||||||
|
|
||||||
// Ignore. Don't move to next column (let the driver figure out what to do).
|
// Ignore. Don't move to next column (let the driver figure out what to do).
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
namespace Terminal.Gui;
|
#nullable enable
|
||||||
|
|
||||||
|
namespace Terminal.Gui;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a single row/column in a Terminal.Gui rendering surface (e.g. <see cref="LineCanvas"/> and
|
/// Represents a single row/column in a Terminal.Gui rendering surface (e.g. <see cref="LineCanvas"/> and
|
||||||
@@ -23,12 +25,12 @@ public record struct Cell (Attribute? Attribute = null, bool IsDirty = false, Ru
|
|||||||
get => _rune;
|
get => _rune;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
CombiningMarks.Clear ();
|
_combiningMarks?.Clear ();
|
||||||
_rune = value;
|
_rune = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Rune> _combiningMarks;
|
private List<Rune>? _combiningMarks;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The combining marks for <see cref="Rune"/> that when combined makes this Cell a combining sequence. If
|
/// The combining marks for <see cref="Rune"/> that when combined makes this Cell a combining sequence. If
|
||||||
@@ -38,10 +40,37 @@ public record struct Cell (Attribute? Attribute = null, bool IsDirty = false, Ru
|
|||||||
/// Only valid in the rare case where <see cref="Rune"/> is a combining sequence that could not be normalized to a
|
/// Only valid in the rare case where <see cref="Rune"/> is a combining sequence that could not be normalized to a
|
||||||
/// single Rune.
|
/// single Rune.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
internal List<Rune> CombiningMarks
|
internal IReadOnlyList<Rune> CombiningMarks
|
||||||
{
|
{
|
||||||
get => _combiningMarks ?? [];
|
// PERFORMANCE: Downside of the interface return type is that List<T> struct enumerator cannot be utilized, i.e. enumerator is allocated.
|
||||||
private set => _combiningMarks = value ?? [];
|
// If enumeration is used heavily in the future then might be better to expose the List<T> Enumerator directly via separate mechanism.
|
||||||
|
get
|
||||||
|
{
|
||||||
|
// Avoid unnecessary list allocation.
|
||||||
|
if (_combiningMarks == null)
|
||||||
|
{
|
||||||
|
return Array.Empty<Rune> ();
|
||||||
|
}
|
||||||
|
return _combiningMarks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds combining mark to the cell.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="combiningMark">The combining mark to add to the cell.</param>
|
||||||
|
internal void AddCombiningMark (Rune combiningMark)
|
||||||
|
{
|
||||||
|
_combiningMarks ??= [];
|
||||||
|
_combiningMarks.Add (combiningMark);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clears combining marks of the cell.
|
||||||
|
/// </summary>
|
||||||
|
internal void ClearCombiningMarks ()
|
||||||
|
{
|
||||||
|
_combiningMarks?.Clear ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
|||||||
Reference in New Issue
Block a user