perf(ui): retain shaped report text
This commit is contained in:
parent
c0bec56dfe
commit
f2a015be8e
11 changed files with 525 additions and 38 deletions
115
src/AcDream.App/UI/Layout/UiTextLayoutCache.cs
Normal file
115
src/AcDream.App/UI/Layout/UiTextLayoutCache.cs
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
using System.Numerics;
|
||||
using AcDream.App.Rendering;
|
||||
|
||||
namespace AcDream.App.UI.Layout;
|
||||
|
||||
/// <summary>
|
||||
/// Retains the shaped line projection of one <see cref="UiText"/> value.
|
||||
/// Controllers publish semantic content; the cache reshapes only when that
|
||||
/// content or the text widget's layout/font inputs change.
|
||||
/// </summary>
|
||||
internal sealed class UiTextLayoutCache<T>
|
||||
{
|
||||
private readonly UiText _target;
|
||||
private readonly Func<UiText, T, IReadOnlyList<UiText.Line>> _shape;
|
||||
private readonly IEqualityComparer<T> _comparer;
|
||||
private readonly Func<T>? _source;
|
||||
private T _value = default!;
|
||||
private bool _hasValue;
|
||||
private bool _shaped;
|
||||
private IReadOnlyList<UiText.Line> _lines = Array.Empty<UiText.Line>();
|
||||
private float _width;
|
||||
private float _padding;
|
||||
private Vector4 _defaultColor;
|
||||
private UiDatFont? _datFont;
|
||||
private BitmapFont? _bitmapFont;
|
||||
private IReadOnlyList<Vector4>? _fontColorPalette;
|
||||
|
||||
public UiTextLayoutCache(
|
||||
UiText target,
|
||||
Func<UiText, T, IReadOnlyList<UiText.Line>> shape,
|
||||
T initialValue,
|
||||
IEqualityComparer<T>? comparer = null)
|
||||
: this(target, shape, source: null, comparer, initialize: true)
|
||||
{
|
||||
SetValue(initialValue);
|
||||
}
|
||||
|
||||
public UiTextLayoutCache(
|
||||
UiText target,
|
||||
Func<UiText, T, IReadOnlyList<UiText.Line>> shape,
|
||||
Func<T> source,
|
||||
IEqualityComparer<T>? comparer = null)
|
||||
: this(
|
||||
target,
|
||||
shape,
|
||||
source ?? throw new ArgumentNullException(nameof(source)),
|
||||
comparer,
|
||||
initialize: true)
|
||||
{
|
||||
}
|
||||
|
||||
private UiTextLayoutCache(
|
||||
UiText target,
|
||||
Func<UiText, T, IReadOnlyList<UiText.Line>> shape,
|
||||
Func<T>? source,
|
||||
IEqualityComparer<T>? comparer,
|
||||
bool initialize)
|
||||
{
|
||||
_ = initialize;
|
||||
_target = target ?? throw new ArgumentNullException(nameof(target));
|
||||
_shape = shape ?? throw new ArgumentNullException(nameof(shape));
|
||||
_source = source;
|
||||
_comparer = comparer ?? EqualityComparer<T>.Default;
|
||||
}
|
||||
|
||||
public Func<IReadOnlyList<UiText.Line>> Provider => GetLines;
|
||||
|
||||
public void SetValue(T value)
|
||||
{
|
||||
if (_hasValue && _comparer.Equals(_value, value))
|
||||
return;
|
||||
|
||||
_value = value;
|
||||
_hasValue = true;
|
||||
_shaped = false;
|
||||
}
|
||||
|
||||
public void Invalidate() => _shaped = false;
|
||||
|
||||
public IReadOnlyList<UiText.Line> GetLines()
|
||||
{
|
||||
if (_source is not null)
|
||||
SetValue(_source());
|
||||
|
||||
if (!_hasValue)
|
||||
return Array.Empty<UiText.Line>();
|
||||
|
||||
if (!_shaped || LayoutChanged())
|
||||
{
|
||||
CaptureLayout();
|
||||
_lines = _shape(_target, _value);
|
||||
_shaped = true;
|
||||
}
|
||||
|
||||
return _lines;
|
||||
}
|
||||
|
||||
private bool LayoutChanged()
|
||||
=> _width != _target.Width
|
||||
|| _padding != _target.Padding
|
||||
|| _defaultColor != _target.DefaultColor
|
||||
|| !ReferenceEquals(_datFont, _target.DatFont)
|
||||
|| !ReferenceEquals(_bitmapFont, _target.Font)
|
||||
|| !ReferenceEquals(_fontColorPalette, _target.FontColorPalette);
|
||||
|
||||
private void CaptureLayout()
|
||||
{
|
||||
_width = _target.Width;
|
||||
_padding = _target.Padding;
|
||||
_defaultColor = _target.DefaultColor;
|
||||
_datFont = _target.DatFont;
|
||||
_bitmapFont = _target.Font;
|
||||
_fontColorPalette = _target.FontColorPalette;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue