Browse Source

Merge remote-tracking branch 'origin/ShapedBufferPooling' into ShapedBufferPooling

pull/9954/head
Sergey Mikolaitis 4 years ago
parent
commit
a73b18a8ee
  1. 8
      src/Avalonia.Base/Media/TextFormatting/ShapedBuffer.cs
  2. 7
      src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs
  3. 3
      src/Avalonia.Controls/Presenters/TextPresenter.cs
  4. 11
      src/Avalonia.Controls/TextBlock.cs
  5. 21
      tests/Avalonia.Benchmarks/Text/HugeTextLayout.cs

8
src/Avalonia.Base/Media/TextFormatting/ShapedBuffer.cs

@ -8,7 +8,7 @@ namespace Avalonia.Media.TextFormatting
public sealed class ShapedBuffer : IList<GlyphInfo>, IDisposable
{
private static readonly IComparer<GlyphInfo> s_clusterComparer = new CompareClusters();
private bool _rented;
private bool _bufferRented;
public ShapedBuffer(CharacterBufferRange characterBufferRange, int bufferLength, IGlyphTypeface glyphTypeface, double fontRenderingEmSize, sbyte bidiLevel) :
this(characterBufferRange,
@ -17,7 +17,7 @@ namespace Avalonia.Media.TextFormatting
fontRenderingEmSize,
bidiLevel)
{
_rented = true;
_bufferRented = true;
Length = bufferLength;
}
@ -272,7 +272,7 @@ namespace Avalonia.Media.TextFormatting
public void Dispose()
{
GC.SuppressFinalize(this);
if (_rented)
if (_bufferRented)
{
GlyphInfos.ReturnRent();
}
@ -280,7 +280,7 @@ namespace Avalonia.Media.TextFormatting
~ShapedBuffer()
{
if (_rented)
if (_bufferRented)
{
GlyphInfos.ReturnRent();
}

7
src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs

@ -981,9 +981,12 @@ namespace Avalonia.Media.TextFormatting
public override void Dispose()
{
foreach (var run in _textRuns.OfType<ShapedTextRun>())
for (int i = 0; i < _textRuns.Count; i++)
{
run.Dispose();
if (_textRuns[i] is ShapedTextRun shapedTextRun)
{
shapedTextRun.Dispose();
}
}
}

3
src/Avalonia.Controls/Presenters/TextPresenter.cs

@ -588,6 +588,7 @@ namespace Avalonia.Controls.Presenters
protected virtual void InvalidateTextLayout()
{
_textLayout?.Dispose();
_textLayout = null;
InvalidateMeasure();
@ -597,6 +598,7 @@ namespace Avalonia.Controls.Presenters
{
_constraint = availableSize;
_textLayout?.Dispose();
_textLayout = null;
InvalidateArrange();
@ -622,6 +624,7 @@ namespace Avalonia.Controls.Presenters
_constraint = new Size(Math.Ceiling(finalSize.Width), double.PositiveInfinity);
_textLayout?.Dispose();
_textLayout = null;
return finalSize;

11
src/Avalonia.Controls/TextBlock.cs

@ -173,13 +173,7 @@ namespace Avalonia.Controls
/// <summary>
/// Gets the <see cref="TextLayout"/> used to render the text.
/// </summary>
public TextLayout TextLayout
{
get
{
return _textLayout ??= CreateTextLayout(_text);
}
}
public TextLayout TextLayout => _textLayout ??= CreateTextLayout(_text);
/// <summary>
/// Gets or sets the padding to place around the <see cref="Text"/>.
@ -648,6 +642,7 @@ namespace Avalonia.Controls
/// </summary>
protected void InvalidateTextLayout()
{
_textLayout?.Dispose();
_textLayout = null;
InvalidateVisual();
@ -663,6 +658,7 @@ namespace Avalonia.Controls
_constraint = availableSize.Deflate(padding);
_textLayout?.Dispose();
_textLayout = null;
var inlines = Inlines;
@ -726,6 +722,7 @@ namespace Avalonia.Controls
_constraint = new Size(Math.Ceiling(finalSize.Deflate(padding).Width), double.PositiveInfinity);
_textLayout?.Dispose();
_textLayout = null;
if (HasComplexContent)

21
tests/Avalonia.Benchmarks/Text/HugeTextLayout.cs

@ -1,5 +1,6 @@
using System;
using System.Linq;
using Avalonia.Controls;
using Avalonia.Media;
using Avalonia.Media.TextFormatting;
using Avalonia.UnitTests;
@ -70,6 +71,26 @@ In respect that the structure of the sufficient amount poses problems and challe
[Benchmark]
public TextLayout[] BuildManySmallTexts() => _manySmallStrings.Select(MakeLayout).ToArray();
[Benchmark]
public void VirtualizeTextBlocks()
{
var blocks = new TextBlock[10];
for (var i = 0; i < blocks.Length; i++)
{
blocks[i] = new TextBlock
{
Width = 120,
Height = 32,
};
}
for (int i = 0, j = 0; i < _manySmallStrings.Length; i++, j = j < blocks.Length - 1 ? j + 1 : 0)
{
blocks[j].Text = _manySmallStrings[i];
blocks[j].Measure(new Size(200, 200));
}
}
private static TextLayout MakeLayout(string str)
{
var layout = new TextLayout(str, Typeface.Default, 12d, Brushes.Black, maxWidth: 120);

Loading…
Cancel
Save