Browse Source

Use IGlyphRunImpl in the IDrawingContextImpl

pull/10015/head
Benedikt Stebner 3 years ago
parent
commit
07c11c75e7
  1. 2
      src/Avalonia.Base/Media/DrawingContext.cs
  2. 5
      src/Avalonia.Base/Media/DrawingGroup.cs
  3. 55
      src/Avalonia.Base/Media/GlyphRun.cs
  4. 15
      src/Avalonia.Base/Media/GlyphRunMetrics.cs
  5. 2
      src/Avalonia.Base/Media/ImmediateDrawingContext.cs
  6. 2
      src/Avalonia.Base/Media/TextDecoration.cs
  7. 2
      src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs
  8. 2
      src/Avalonia.Base/Platform/IDrawingContextImpl.cs
  9. 19
      src/Avalonia.Base/Platform/IGlyphRunImpl.cs
  10. 2
      src/Avalonia.Base/Rendering/Composition/Drawing/CompositionDrawingContext.cs
  11. 2
      src/Avalonia.Base/Rendering/Composition/Server/DrawingContextProxy.cs
  12. 2
      src/Avalonia.Base/Rendering/Composition/Server/FpsCounter.cs
  13. 2
      src/Avalonia.Base/Rendering/SceneGraph/DeferredDrawingContextImpl.cs
  14. 18
      src/Avalonia.Base/Rendering/SceneGraph/GlyphRunNode.cs
  15. 8
      src/Avalonia.Headless/HeadlessPlatformRenderInterface.cs
  16. 10
      src/Skia/Avalonia.Skia/DrawingContextImpl.cs
  17. 10
      src/Skia/Avalonia.Skia/GlyphRunImpl.cs
  18. 14
      src/Skia/Avalonia.Skia/PlatformRenderInterface.cs
  19. 14
      src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs
  20. 8
      src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs
  21. 12
      src/Windows/Avalonia.Direct2D1/Media/GlyphRunImpl.cs
  22. 4
      tests/Avalonia.Base.UnitTests/Media/GlyphRunTests.cs
  23. 2
      tests/Avalonia.Benchmarks/NullDrawingContextImpl.cs
  24. 4
      tests/Avalonia.Benchmarks/NullGlyphRun.cs
  25. 2
      tests/Avalonia.Benchmarks/NullRenderingPlatform.cs
  26. 3
      tests/Avalonia.Controls.UnitTests/DatePickerTests.cs
  27. 8
      tests/Avalonia.Controls.UnitTests/MaskedTextBoxTests.cs
  28. 4
      tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs
  29. 3
      tests/Avalonia.Controls.UnitTests/TimePickerTests.cs
  30. 4
      tests/Avalonia.Skia.UnitTests/Media/GlyphRunTests.cs
  31. 11
      tests/Avalonia.UnitTests/MockGlyphRun.cs
  32. 2
      tests/Avalonia.UnitTests/MockPlatformRenderInterface.cs

2
src/Avalonia.Base/Media/DrawingContext.cs

@ -246,7 +246,7 @@ namespace Avalonia.Media
if (foreground != null)
{
PlatformImpl.DrawGlyphRun(foreground, glyphRun);
PlatformImpl.DrawGlyphRun(foreground, glyphRun.PlatformImpl);
}
}

5
src/Avalonia.Base/Media/DrawingGroup.cs

@ -167,18 +167,17 @@ namespace Avalonia.Media
AddNewGeometryDrawing(brush, pen, new PlatformGeometry(geometry));
}
public void DrawGlyphRun(IBrush foreground, GlyphRun glyphRun)
public void DrawGlyphRun(IBrush foreground, IRef<IGlyphRunImpl> glyphRun)
{
if (foreground == null || glyphRun == null)
{
return;
}
// Add a GlyphRunDrawing to the Drawing graph
GlyphRunDrawing glyphRunDrawing = new GlyphRunDrawing
{
Foreground = foreground,
GlyphRun = glyphRun,
GlyphRun = new GlyphRun(glyphRun)
};
// Add Drawing to the Drawing graph

55
src/Avalonia.Base/Media/GlyphRun.cs

@ -13,10 +13,9 @@ namespace Avalonia.Media
/// </summary>
public sealed class GlyphRun : IDisposable
{
private IGlyphRunImpl? _glyphRunImpl;
private IRef<IGlyphRunImpl>? _platformImpl;
private double _fontRenderingEmSize;
private int _biDiLevel;
private Point? _baselineOrigin;
private GlyphRunMetrics? _glyphRunMetrics;
private ReadOnlyMemory<char> _characters;
private IReadOnlyList<GlyphInfo> _glyphInfos;
@ -68,6 +67,13 @@ namespace Avalonia.Media
_biDiLevel = biDiLevel;
}
internal GlyphRun(IRef<IGlyphRunImpl> platformImpl)
{
_glyphInfos = Array.Empty<GlyphInfo>();
GlyphTypeface = Typeface.Default.GlyphTypeface;
_platformImpl = platformImpl;
}
private static IReadOnlyList<GlyphInfo> CreateGlyphInfos(IReadOnlyList<ushort> glyphIndices,
double fontRenderingEmSize, IGlyphTypeface glyphTypeface)
{
@ -132,7 +138,7 @@ namespace Avalonia.Media
/// <summary>
/// Gets or sets the conservative bounding box of the <see cref="GlyphRun"/>.
/// </summary>
public Size Size => new Size(Metrics.WidthIncludingTrailingWhitespace, Metrics.Height);
public Size Size => PlatformImpl.Item.Size;
/// <summary>
///
@ -141,13 +147,9 @@ namespace Avalonia.Media
=> _glyphRunMetrics ??= CreateGlyphRunMetrics();
/// <summary>
/// Gets or sets the baseline origin of the<see cref="GlyphRun"/>.
/// Gets the baseline origin of the<see cref="GlyphRun"/>.
/// </summary>
public Point BaselineOrigin
{
get => _baselineOrigin ??= CalculateBaselineOrigin();
set => Set(ref _baselineOrigin, value);
}
public Point BaselineOrigin => PlatformImpl.Item.BaselineOrigin;
/// <summary>
/// Gets or sets the list of UTF16 code points that represent the Unicode content of the <see cref="GlyphRun"/>.
@ -193,8 +195,8 @@ namespace Avalonia.Media
/// <summary>
/// The platform implementation of the <see cref="GlyphRun"/>.
/// </summary>
public IGlyphRunImpl GlyphRunImpl
=> _glyphRunImpl ??= CreateGlyphRunImpl();
public IRef<IGlyphRunImpl> PlatformImpl
=> _platformImpl ??= CreateGlyphRunImpl();
/// <summary>
/// Obtains geometry for the glyph run.
@ -233,7 +235,7 @@ namespace Avalonia.Media
if (characterIndex > Metrics.LastCluster)
{
return Metrics.WidthIncludingTrailingWhitespace;
return Size.Width;
}
var glyphIndex = FindGlyphIndex(characterIndex);
@ -607,15 +609,6 @@ namespace Avalonia.Media
return new CharacterHit(cluster, clusterLength);
}
/// <summary>
/// Calculates the default baseline origin of the <see cref="GlyphRun"/>.
/// </summary>
/// <returns>The baseline origin.</returns>
private Point CalculateBaselineOrigin()
{
return new Point(0, -GlyphTypeface.Metrics.Ascent * Scale);
}
private GlyphRunMetrics CreateGlyphRunMetrics()
{
int firstCluster, lastCluster;
@ -668,8 +661,6 @@ namespace Avalonia.Media
return new GlyphRunMetrics(
width,
widthIncludingTrailingWhitespace,
height,
trailingWhitespaceLength,
newLineLength,
firstCluster,
@ -800,28 +791,30 @@ namespace Avalonia.Media
private void Set<T>(ref T field, T value)
{
_glyphRunImpl?.Dispose();
_platformImpl?.Dispose();
_glyphRunImpl = null;
_platformImpl = null;
_glyphRunMetrics = null;
_baselineOrigin = null;
field = value;
}
private IGlyphRunImpl CreateGlyphRunImpl()
private IRef<IGlyphRunImpl> CreateGlyphRunImpl()
{
var platformRenderInterface = AvaloniaLocator.Current.GetRequiredService<IPlatformRenderInterface>();
return platformRenderInterface.CreateGlyphRun(GlyphTypeface, FontRenderingEmSize, GlyphInfos);
var platformImpl = platformRenderInterface.CreateGlyphRun(GlyphTypeface, FontRenderingEmSize, GlyphInfos);
_platformImpl = RefCountable.Create(platformImpl);
return _platformImpl;
}
public void Dispose()
{
_glyphRunImpl?.Dispose();
_glyphRunImpl = null;
_platformImpl?.Dispose();
_platformImpl = null;
}
}
}

15
src/Avalonia.Base/Media/GlyphRunMetrics.cs

@ -2,27 +2,20 @@
{
public readonly record struct GlyphRunMetrics
{
public GlyphRunMetrics(double width, double widthIncludingTrailingWhitespace, double height,
int trailingWhitespaceLength, int newLineLength, int firstCluster, int lastCluster)
public GlyphRunMetrics(double width, int trailingWhitespaceLength, int newLineLength, int firstCluster, int lastCluster)
{
Width = width;
WidthIncludingTrailingWhitespace = widthIncludingTrailingWhitespace;
Height = height;
TrailingWhitespaceLength = trailingWhitespaceLength;
NewLineLength= newLineLength;
NewLineLength = newLineLength;
FirstCluster = firstCluster;
LastCluster = lastCluster;
}
public double Width { get; }
public double WidthIncludingTrailingWhitespace { get; }
public double Height { get; }
public int TrailingWhitespaceLength { get; }
public int NewLineLength { get; }
public int NewLineLength { get; }
public int FirstCluster { get; }

2
src/Avalonia.Base/Media/ImmediateDrawingContext.cs

@ -182,7 +182,7 @@ namespace Avalonia.Media
/// </summary>
/// <param name="foreground">The foreground brush.</param>
/// <param name="glyphRun">The glyph run.</param>
public void DrawGlyphRun(IImmutableBrush foreground, GlyphRun glyphRun)
public void DrawGlyphRun(IImmutableBrush foreground, IRef<IGlyphRunImpl> glyphRun)
{
_ = glyphRun ?? throw new ArgumentNullException(nameof(glyphRun));

2
src/Avalonia.Base/Media/TextDecoration.cs

@ -218,7 +218,7 @@ namespace Avalonia.Media
{
var offsetY = glyphRun.BaselineOrigin.Y - origin.Y;
var intersections = glyphRun.GlyphRunImpl.GetIntersections((float)(thickness * 0.5d - offsetY), (float)(thickness * 1.5d - offsetY));
var intersections = glyphRun.PlatformImpl.Item.GetIntersections((float)(thickness * 0.5d - offsetY), (float)(thickness * 1.5d - offsetY));
if (intersections != null && intersections.Count > 0)
{

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

@ -1320,7 +1320,7 @@ namespace Avalonia.Media.TextFormatting
newLineLength = textRun.GlyphRun.Metrics.NewLineLength;
}
widthIncludingWhitespace += textRun.GlyphRun.Metrics.WidthIncludingTrailingWhitespace;
widthIncludingWhitespace += textRun.Size.Width;
break;
}

2
src/Avalonia.Base/Platform/IDrawingContextImpl.cs

@ -91,7 +91,7 @@ namespace Avalonia.Platform
/// </summary>
/// <param name="foreground">The foreground.</param>
/// <param name="glyphRun">The glyph run.</param>
void DrawGlyphRun(IBrush foreground, GlyphRun glyphRun);
void DrawGlyphRun(IBrush foreground, IRef<IGlyphRunImpl> glyphRun);
/// <summary>
/// Creates a new <see cref="IRenderTargetBitmapImpl"/> that can be used as a render layer

19
src/Avalonia.Base/Platform/IGlyphRunImpl.cs

@ -10,6 +10,23 @@ namespace Avalonia.Platform
[Unstable]
public interface IGlyphRunImpl : IDisposable
{
IReadOnlyList<float> GetIntersections(float lowerBound, float upperBound);
/// <summary>
/// Gets the conservative bounding box of the glyph run./>.
/// </summary>
Size Size { get; }
/// <summary>
/// Gets the baseline origin of the glyph run./>.
/// </summary>
Point BaselineOrigin { get; }
/// <summary>
/// Gets the intersections of specified upper and lower limit.
/// </summary>
/// <param name="lowerLimit">Upper limit.</param>
/// <param name="upperLimit">Lower limit.</param>
/// <returns></returns>
IReadOnlyList<float> GetIntersections(float lowerLimit, float upperLimit);
}
}

2
src/Avalonia.Base/Rendering/Composition/Drawing/CompositionDrawingContext.cs

@ -159,7 +159,7 @@ internal class CompositionDrawingContext : IDrawingContextImpl, IDrawingContextW
public object? GetFeature(Type t) => null;
/// <inheritdoc/>
public void DrawGlyphRun(IBrush foreground, GlyphRun glyphRun)
public void DrawGlyphRun(IBrush foreground, IRef<IGlyphRunImpl> glyphRun)
{
var next = NextDrawAs<GlyphRunNode>();

2
src/Avalonia.Base/Rendering/Composition/Server/DrawingContextProxy.cs

@ -86,7 +86,7 @@ internal class CompositorDrawingContextProxy : IDrawingContextImpl, IDrawingCont
_impl.DrawEllipse(brush, pen, rect);
}
public void DrawGlyphRun(IBrush foreground, GlyphRun glyphRun)
public void DrawGlyphRun(IBrush foreground, IRef<IGlyphRunImpl> glyphRun)
{
_impl.DrawGlyphRun(foreground, glyphRun);
}

2
src/Avalonia.Base/Rendering/Composition/Server/FpsCounter.cs

@ -72,7 +72,7 @@ internal class FpsCounter
{
var run = _runs[ch - FirstChar];
context.Transform = Matrix.CreateTranslation(offset, 0);
context.DrawGlyphRun(Brushes.White, run);
context.DrawGlyphRun(Brushes.White, run.PlatformImpl);
offset += run.Size.Width;
}
}

2
src/Avalonia.Base/Rendering/SceneGraph/DeferredDrawingContextImpl.cs

@ -206,7 +206,7 @@ namespace Avalonia.Rendering.SceneGraph
public object? GetFeature(Type t) => null;
/// <inheritdoc/>
public void DrawGlyphRun(IBrush foreground, GlyphRun glyphRun)
public void DrawGlyphRun(IBrush foreground, IRef<IGlyphRunImpl> glyphRun)
{
var next = NextDrawAs<GlyphRunNode>();

18
src/Avalonia.Base/Rendering/SceneGraph/GlyphRunNode.cs

@ -1,6 +1,7 @@
using System;
using Avalonia.Media;
using Avalonia.Platform;
using Avalonia.Utilities;
namespace Avalonia.Rendering.SceneGraph
{
@ -19,13 +20,13 @@ namespace Avalonia.Rendering.SceneGraph
public GlyphRunNode(
Matrix transform,
IBrush foreground,
GlyphRun glyphRun,
IRef<IGlyphRunImpl> glyphRun,
IDisposable? aux = null)
: base(new Rect(glyphRun.Size), transform, aux)
: base(new Rect(glyphRun.Item.Size), transform, aux)
{
Transform = transform;
Foreground = foreground.ToImmutable();
GlyphRun = glyphRun;
GlyphRun = glyphRun.Clone();
}
/// <summary>
@ -41,7 +42,7 @@ namespace Avalonia.Rendering.SceneGraph
/// <summary>
/// Gets the glyph run to draw.
/// </summary>
public GlyphRun GlyphRun { get; }
public IRef<IGlyphRunImpl> GlyphRun { get; }
/// <inheritdoc/>
public override void Render(IDrawingContextImpl context)
@ -61,14 +62,19 @@ namespace Avalonia.Rendering.SceneGraph
/// The properties of the other draw operation are passed in as arguments to prevent
/// allocation of a not-yet-constructed draw operation object.
/// </remarks>
internal bool Equals(Matrix transform, IBrush foreground, GlyphRun glyphRun)
internal bool Equals(Matrix transform, IBrush foreground, IRef<IGlyphRunImpl> glyphRun)
{
return transform == Transform &&
Equals(foreground, Foreground) &&
Equals(glyphRun, GlyphRun);
Equals(glyphRun.Item, GlyphRun.Item);
}
/// <inheritdoc/>
public override bool HitTest(Point p) => Bounds.ContainsExclusive(p);
public override void Dispose()
{
GlyphRun?.Dispose();
}
}
}

8
src/Avalonia.Headless/HeadlessPlatformRenderInterface.cs

@ -126,13 +126,17 @@ namespace Avalonia.Headless
class HeadlessGlyphRunStub : IGlyphRunImpl
{
public Size Size => new Size(8, 12);
public Point BaselineOrigin => new Point(0, 8);
public void Dispose()
{
}
public IReadOnlyList<float> GetIntersections(float lowerBound, float upperBound)
{
throw new NotImplementedException();
return null;
}
}
@ -463,7 +467,7 @@ namespace Avalonia.Headless
{
}
public void DrawGlyphRun(IBrush foreground, GlyphRun glyphRun)
public void DrawGlyphRun(IBrush foreground, IRef<IGlyphRunImpl> glyphRun)
{
}

10
src/Skia/Avalonia.Skia/DrawingContextImpl.cs

@ -492,15 +492,15 @@ namespace Avalonia.Skia
}
/// <inheritdoc />
public void DrawGlyphRun(IBrush foreground, GlyphRun glyphRun)
public void DrawGlyphRun(IBrush foreground, IRef<IGlyphRunImpl> glyphRun)
{
CheckLease();
using (var paintWrapper = CreatePaint(_fillPaint, foreground, glyphRun.Size))
using (var paintWrapper = CreatePaint(_fillPaint, foreground, glyphRun.Item.Size))
{
var glyphRunImpl = (GlyphRunImpl)glyphRun.GlyphRunImpl;
var glyphRunImpl = (GlyphRunImpl)glyphRun.Item;
Canvas.DrawText(glyphRunImpl.TextBlob, (float)glyphRun.BaselineOrigin.X,
(float)glyphRun.BaselineOrigin.Y, paintWrapper.Paint);
Canvas.DrawText(glyphRunImpl.TextBlob, (float)glyphRun.Item.BaselineOrigin.X,
(float)glyphRun.Item.BaselineOrigin.Y, paintWrapper.Paint);
}
}

10
src/Skia/Avalonia.Skia/GlyphRunImpl.cs

@ -11,9 +11,13 @@ namespace Avalonia.Skia
[Unstable]
public class GlyphRunImpl : IGlyphRunImpl
{
public GlyphRunImpl(SKTextBlob textBlob)
public GlyphRunImpl(SKTextBlob textBlob, Size size, Point baselineOrigin)
{
TextBlob = textBlob ?? throw new ArgumentNullException (nameof (textBlob));
Size = size;
BaselineOrigin = baselineOrigin;
}
/// <summary>
@ -21,6 +25,10 @@ namespace Avalonia.Skia
/// </summary>
public SKTextBlob TextBlob { get; }
public Size Size { get; }
public Point BaselineOrigin { get; }
public IReadOnlyList<float> GetIntersections(float upperBound, float lowerBound) =>
TextBlob.GetIntercepts(lowerBound, upperBound);

14
src/Skia/Avalonia.Skia/PlatformRenderInterface.cs

@ -81,7 +81,7 @@ namespace Avalonia.Skia
SKPath path = new SKPath();
var (currentX, currentY) = glyphRun.BaselineOrigin;
var (currentX, currentY) = glyphRun.PlatformImpl.Item.BaselineOrigin;
for (var i = 0; i < glyphRun.GlyphInfos.Count; i++)
{
@ -236,7 +236,7 @@ namespace Avalonia.Skia
var glyphSpan = runBuffer.GetGlyphSpan();
var positionSpan = runBuffer.GetPositionSpan();
var currentX = 0.0;
var width = 0.0;
for (int i = 0; i < count; i++)
{
@ -245,12 +245,16 @@ namespace Avalonia.Skia
glyphSpan[i] = glyphInfo.GlyphIndex;
positionSpan[i] = new SKPoint((float)(currentX + offset.X), (float)offset.Y);
positionSpan[i] = new SKPoint((float)(width + offset.X), (float)offset.Y);
currentX += glyphInfo.GlyphAdvance;
width += glyphInfo.GlyphAdvance;
}
return new GlyphRunImpl(builder.Build());
var scale = fontRenderingEmSize / glyphTypeface.Metrics.DesignEmHeight;
var height = glyphTypeface.Metrics.LineSpacing * scale;
var baselineOrigin = new Point(0, -glyphTypeface.Metrics.Ascent * scale);
return new GlyphRunImpl(builder.Build(), new Size(width, height), baselineOrigin);
}
}
}

14
src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs

@ -181,9 +181,15 @@ namespace Avalonia.Direct2D1
run.Advances = new float[glyphCount];
var width = 0.0;
for (var i = 0; i < glyphCount; i++)
{
run.Advances[i] = (float)glyphInfos[i].GlyphAdvance;
var advance = glyphInfos[i].GlyphAdvance;
width += advance;
run.Advances[i] = (float)advance;
}
run.Offsets = new GlyphOffset[glyphCount];
@ -199,7 +205,11 @@ namespace Avalonia.Direct2D1
};
}
return new GlyphRunImpl(run);
var scale = fontRenderingEmSize / glyphTypeface.Metrics.DesignEmHeight;
var height = glyphTypeface.Metrics.LineSpacing * scale;
var baselineOrigin = new Point(0, -glyphTypeface.Metrics.Ascent * scale);
return new GlyphRunImpl(run, new Size(width, height), baselineOrigin);
}
class D2DApi : IPlatformRenderInterfaceContext

8
src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs

@ -390,13 +390,13 @@ namespace Avalonia.Direct2D1.Media
/// </summary>
/// <param name="foreground">The foreground.</param>
/// <param name="glyphRun">The glyph run.</param>
public void DrawGlyphRun(IBrush foreground, GlyphRun glyphRun)
public void DrawGlyphRun(IBrush foreground, IRef<IGlyphRunImpl> glyphRun)
{
using (var brush = CreateBrush(foreground, glyphRun.Size))
using (var brush = CreateBrush(foreground, glyphRun.Item.Size))
{
var glyphRunImpl = (GlyphRunImpl)glyphRun.GlyphRunImpl;
var glyphRunImpl = (GlyphRunImpl)glyphRun.Item;
_renderTarget.DrawGlyphRun(glyphRun.BaselineOrigin.ToSharpDX(), glyphRunImpl.GlyphRun,
_renderTarget.DrawGlyphRun(glyphRun.Item.BaselineOrigin.ToSharpDX(), glyphRunImpl.GlyphRun,
brush.PlatformBrush, MeasuringMode.Natural);
}
}

12
src/Windows/Avalonia.Direct2D1/Media/GlyphRunImpl.cs

@ -1,20 +1,26 @@
using System.Collections.Generic;
using Avalonia.Platform;
using SharpDX.DirectWrite;
namespace Avalonia.Direct2D1.Media
{
internal class GlyphRunImpl : IGlyphRunImpl
{
public GlyphRunImpl(SharpDX.DirectWrite.GlyphRun glyphRun)
public GlyphRunImpl(GlyphRun glyphRun, Size size, Point baselineOrigin)
{
Size = size;
BaselineOrigin = baselineOrigin;
GlyphRun = glyphRun;
}
public SharpDX.DirectWrite.GlyphRun GlyphRun { get; }
public Size Size { get; }
public Point BaselineOrigin { get; }
public GlyphRun GlyphRun { get; }
public void Dispose()
{
//SharpDX already handles this.
//GlyphRun?.Dispose();
}

4
tests/Avalonia.Base.UnitTests/Media/GlyphRunTests.cs

@ -25,7 +25,7 @@ namespace Avalonia.Base.UnitTests.Media
[Theory]
public void Should_Get_Distance_From_CharacterHit(double[] advances, int[] clusters, int start, int trailingLength, double expectedDistance)
{
using(UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
using(UnitTestApplication.Start(TestServices.StyledWindow))
using (var glyphRun = CreateGlyphRun(advances, clusters))
{
var characterHit = new CharacterHit(start, trailingLength);
@ -44,7 +44,7 @@ namespace Avalonia.Base.UnitTests.Media
public void Should_Get_CharacterHit_FromDistance(double[] advances, int[] clusters, double distance, int start,
int trailingLengthExpected, bool isInsideExpected)
{
using(UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
using(UnitTestApplication.Start(TestServices.StyledWindow))
using (var glyphRun = CreateGlyphRun(advances, clusters))
{
var textBounds = glyphRun.GetCharacterHitFromDistance(distance, out var isInside);

2
tests/Avalonia.Benchmarks/NullDrawingContextImpl.cs

@ -44,7 +44,7 @@ namespace Avalonia.Benchmarks
{
}
public void DrawGlyphRun(IBrush foreground, GlyphRun glyphRun)
public void DrawGlyphRun(IBrush foreground, IRef<IGlyphRunImpl> glyphRun)
{
}

4
tests/Avalonia.Benchmarks/NullGlyphRun.cs

@ -5,6 +5,10 @@ namespace Avalonia.Benchmarks
{
internal class NullGlyphRun : IGlyphRunImpl
{
public Size Size => default;
public Point BaselineOrigin => default;
public void Dispose()
{
}

2
tests/Avalonia.Benchmarks/NullRenderingPlatform.cs

@ -123,7 +123,7 @@ namespace Avalonia.Benchmarks
public IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize, IReadOnlyList<GlyphInfo> glyphInfos)
{
return new MockGlyphRun();
return new MockGlyphRun(glyphInfos);
}
public IPlatformRenderInterfaceContext CreateBackendContext(IPlatformGraphicsContext graphicsContext)

3
tests/Avalonia.Controls.UnitTests/DatePickerTests.cs

@ -205,7 +205,8 @@ namespace Avalonia.Controls.UnitTests
private static TestServices Services => TestServices.MockThreadingInterface.With(
fontManagerImpl: new MockFontManagerImpl(),
standardCursorFactory: Mock.Of<ICursorFactory>(),
textShaperImpl: new MockTextShaperImpl());
textShaperImpl: new MockTextShaperImpl(),
renderInterface: new MockPlatformRenderInterface());
private static IControlTemplate CreateTemplate()
{

8
tests/Avalonia.Controls.UnitTests/MaskedTextBoxTests.cs

@ -107,7 +107,7 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void CaretIndex_Can_Moved_To_Position_After_The_End_Of_Text_With_Arrow_Key()
{
using (Start())
using (Start(TestServices.StyledWindow))
{
var target = new MaskedTextBox
{
@ -182,7 +182,7 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Control_Backspace_Should_Remove_The_Word_Before_The_Caret_If_There_Is_No_Selection()
{
using (Start())
using (Start(TestServices.StyledWindow))
{
MaskedTextBox textBox = new MaskedTextBox
{
@ -224,7 +224,7 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Control_Delete_Should_Remove_The_Word_After_The_Caret_If_There_Is_No_Selection()
{
using (Start())
using (Start(TestServices.StyledWindow))
{
var textBox = new MaskedTextBox
{
@ -810,7 +810,7 @@ namespace Avalonia.Controls.UnitTests
bool fromClipboard,
string expected)
{
using (Start())
using (Start(TestServices.StyledWindow))
{
var target = new MaskedTextBox
{

4
tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs

@ -2131,9 +2131,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
private static IDisposable Start()
{
return UnitTestApplication.Start(new TestServices(
fontManagerImpl: new MockFontManagerImpl(),
textShaperImpl: new MockTextShaperImpl()));
return UnitTestApplication.Start(TestServices.StyledWindow);
}
private static void Prepare(SelectingItemsControl target)

3
tests/Avalonia.Controls.UnitTests/TimePickerTests.cs

@ -101,7 +101,8 @@ namespace Avalonia.Controls.UnitTests
private static TestServices Services => TestServices.MockThreadingInterface.With(
fontManagerImpl: new MockFontManagerImpl(),
standardCursorFactory: Mock.Of<ICursorFactory>(),
textShaperImpl: new MockTextShaperImpl());
textShaperImpl: new MockTextShaperImpl(),
renderInterface: new MockPlatformRenderInterface());
private static IControlTemplate CreateTemplate()
{

4
tests/Avalonia.Skia.UnitTests/Media/GlyphRunTests.cs

@ -110,7 +110,7 @@ namespace Avalonia.Skia.UnitTests.Media
if (glyphRun.IsLeftToRight)
{
var characterHit =
glyphRun.GetCharacterHitFromDistance(glyphRun.Metrics.WidthIncludingTrailingWhitespace, out _);
glyphRun.GetCharacterHitFromDistance(glyphRun.Size.Width, out _);
Assert.Equal(glyphRun.Characters.Length, characterHit.FirstCharacterIndex + characterHit.TrailingLength);
}
@ -159,7 +159,7 @@ namespace Avalonia.Skia.UnitTests.Media
{
var height = glyphRun.Size.Height;
var currentX = glyphRun.IsLeftToRight ? 0d : glyphRun.Metrics.WidthIncludingTrailingWhitespace;
var currentX = glyphRun.IsLeftToRight ? 0d : glyphRun.Size.Width;
var rects = new List<Rect>(glyphRun.GlyphInfos!.Count);

11
tests/Avalonia.UnitTests/MockGlyphRun.cs

@ -1,10 +1,21 @@
using System.Collections.Generic;
using System.Linq;
using Avalonia.Media.TextFormatting;
using Avalonia.Platform;
namespace Avalonia.UnitTests
{
public class MockGlyphRun : IGlyphRunImpl
{
public MockGlyphRun(IReadOnlyList<GlyphInfo> glyphInfos)
{
Size = new Size(glyphInfos.Sum(x=> x.GlyphAdvance), 10);
}
public Size Size { get; }
public Point BaselineOrigin => new Point(0, 8);
public void Dispose()
{

2
tests/Avalonia.UnitTests/MockPlatformRenderInterface.cs

@ -149,7 +149,7 @@ namespace Avalonia.UnitTests
public IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize, IReadOnlyList<GlyphInfo> glyphInfos)
{
return Mock.Of<IGlyphRunImpl>();
return new MockGlyphRun(glyphInfos);
}
public IPlatformRenderInterfaceContext CreateBackendContext(IPlatformGraphicsContext graphicsContext) => this;

Loading…
Cancel
Save