Browse Source
[WIP] Reuse text and geometry related headless mocks in Avalonia unit test and benchmarkspull/11146/head
committed by
GitHub
40 changed files with 246 additions and 1353 deletions
@ -1,285 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.IO; |
|
||||
using Avalonia.Media; |
|
||||
using Avalonia.Platform; |
|
||||
using Avalonia.UnitTests; |
|
||||
using Avalonia.Media.Imaging; |
|
||||
using Avalonia.Media.TextFormatting; |
|
||||
|
|
||||
namespace Avalonia.Base.UnitTests.VisualTree |
|
||||
{ |
|
||||
class MockRenderInterface : IPlatformRenderInterface, IPlatformRenderInterfaceContext |
|
||||
{ |
|
||||
public IRenderTarget CreateRenderTarget(IEnumerable<object> surfaces) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public bool IsLost => false; |
|
||||
|
|
||||
public object TryGetFeature(Type featureType) => null; |
|
||||
|
|
||||
public IRenderTargetBitmapImpl CreateRenderTargetBitmap(PixelSize size, Vector dpi) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IStreamGeometryImpl CreateStreamGeometry() |
|
||||
{ |
|
||||
return new MockStreamGeometry(); |
|
||||
} |
|
||||
|
|
||||
public IGeometryImpl CreateGeometryGroup(FillRule fillRule, IReadOnlyList<IGeometryImpl> children) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IGeometryImpl CreateCombinedGeometry(GeometryCombineMode combineMode, IGeometryImpl g1, IGeometryImpl g2) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IBitmapImpl LoadBitmap(Stream stream) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IWriteableBitmapImpl LoadWriteableBitmapToWidth(Stream stream, int width, |
|
||||
BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IWriteableBitmapImpl LoadWriteableBitmapToHeight(Stream stream, int height, |
|
||||
BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IWriteableBitmapImpl LoadWriteableBitmap(string fileName) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IWriteableBitmapImpl LoadWriteableBitmap(Stream stream) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IBitmapImpl LoadBitmap(string fileName) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IBitmapImpl LoadBitmap(PixelFormat format, AlphaFormat alphaFormat, IntPtr data, PixelSize size, Vector dpi, int stride) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize, |
|
||||
IReadOnlyList<GlyphInfo> glyphInfos, Point baselineOrigin, Rect bounds) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IPlatformRenderInterfaceContext CreateBackendContext(IPlatformGraphicsContext graphicsContext) |
|
||||
{ |
|
||||
return this; |
|
||||
} |
|
||||
|
|
||||
public bool SupportsIndividualRoundRects { get; set; } |
|
||||
public AlphaFormat DefaultAlphaFormat { get; } |
|
||||
public PixelFormat DefaultPixelFormat { get; } |
|
||||
public bool IsSupportedBitmapPixelFormat(PixelFormat format) => true; |
|
||||
|
|
||||
public IFontManagerImpl CreateFontManager() |
|
||||
{ |
|
||||
return new MockFontManagerImpl(); |
|
||||
} |
|
||||
|
|
||||
public IWriteableBitmapImpl CreateWriteableBitmap(PixelSize size, Vector dpi, PixelFormat fmt, AlphaFormat alphaFormat) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IGeometryImpl CreateEllipseGeometry(Rect rect) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IGeometryImpl CreateLineGeometry(Point p1, Point p2) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IGeometryImpl CreateRectangleGeometry(Rect rect) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IBitmapImpl LoadBitmapToWidth(Stream stream, int width, BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IBitmapImpl LoadBitmapToHeight(Stream stream, int height, BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IBitmapImpl ResizeBitmap(IBitmapImpl bitmapImpl, PixelSize destinationSize, BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IGeometryImpl BuildGlyphRunGeometry(GlyphRun glyphRun) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
class MockStreamGeometry : IStreamGeometryImpl |
|
||||
{ |
|
||||
private MockStreamGeometryContext _impl = new MockStreamGeometryContext(); |
|
||||
public Rect Bounds |
|
||||
{ |
|
||||
get |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public double ContourLength { get; } |
|
||||
|
|
||||
public IStreamGeometryImpl Clone() |
|
||||
{ |
|
||||
return this; |
|
||||
} |
|
||||
|
|
||||
public void Dispose() |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public bool FillContains(Point point) |
|
||||
{ |
|
||||
return _impl.FillContains(point); |
|
||||
} |
|
||||
|
|
||||
public Rect GetRenderBounds(IPen pen) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IGeometryImpl Intersect(IGeometryImpl geometry) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IStreamGeometryContextImpl Open() |
|
||||
{ |
|
||||
return _impl; |
|
||||
} |
|
||||
|
|
||||
public bool StrokeContains(IPen pen, Point point) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public ITransformedGeometryImpl WithTransform(Matrix transform) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public bool TryGetPointAtDistance(double distance, out Point point) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public bool TryGetPointAndTangentAtDistance(double distance, out Point point, out Point tangent) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public bool TryGetSegment(double startDistance, double stopDistance, bool startOnBeginFigure, out IGeometryImpl segmentGeometry) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
class MockStreamGeometryContext : IStreamGeometryContextImpl |
|
||||
{ |
|
||||
private List<Point> points = new List<Point>(); |
|
||||
public void ArcTo(Point point, Size size, double rotationAngle, bool isLargeArc, SweepDirection sweepDirection) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public void BeginFigure(Point startPoint, bool isFilled) |
|
||||
{ |
|
||||
points.Add(startPoint); |
|
||||
} |
|
||||
|
|
||||
public void CubicBezierTo(Point point1, Point point2, Point point3) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public void Dispose() |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public void EndFigure(bool isClosed) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public void LineTo(Point point) |
|
||||
{ |
|
||||
points.Add(point); |
|
||||
} |
|
||||
|
|
||||
public void QuadraticBezierTo(Point control, Point endPoint) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public void SetFillRule(FillRule fillRule) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public bool FillContains(Point point) |
|
||||
{ |
|
||||
// Use the algorithm from https://www.blackpawn.com/texts/pointinpoly/default.html
|
|
||||
// to determine if the point is in the geometry (since it will always be convex in this situation)
|
|
||||
for (int i = 0; i < points.Count; i++) |
|
||||
{ |
|
||||
var a = points[i]; |
|
||||
var b = points[(i + 1) % points.Count]; |
|
||||
var c = points[(i + 2) % points.Count]; |
|
||||
|
|
||||
Vector v0 = c - a; |
|
||||
Vector v1 = b - a; |
|
||||
Vector v2 = point - a; |
|
||||
|
|
||||
var dot00 = v0 * v0; |
|
||||
var dot01 = v0 * v1; |
|
||||
var dot02 = v0 * v2; |
|
||||
var dot11 = v1 * v1; |
|
||||
var dot12 = v1 * v2; |
|
||||
|
|
||||
|
|
||||
var invDenom = 1 / (dot00 * dot11 - dot01 * dot01); |
|
||||
var u = (dot11 * dot02 - dot01 * dot12) * invDenom; |
|
||||
var v = (dot00 * dot12 - dot01 * dot02) * invDenom; |
|
||||
if ((u >= 0) && (v >= 0) && (u + v < 1)) return true; |
|
||||
} |
|
||||
return false; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public void Dispose() |
|
||||
{ |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
@ -1,17 +0,0 @@ |
|||||
using System; |
|
||||
using Avalonia.Input; |
|
||||
using Avalonia.Platform; |
|
||||
|
|
||||
namespace Avalonia.Benchmarks |
|
||||
{ |
|
||||
internal class NullCursorFactory : ICursorFactory |
|
||||
{ |
|
||||
public ICursorImpl CreateCursor(IBitmapImpl cursor, PixelPoint hotSpot) => new NullCursorImpl(); |
|
||||
ICursorImpl ICursorFactory.GetCursor(StandardCursorType cursorType) => new NullCursorImpl(); |
|
||||
|
|
||||
private class NullCursorImpl : ICursorImpl |
|
||||
{ |
|
||||
public void Dispose() { } |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,107 +0,0 @@ |
|||||
using System; |
|
||||
using Avalonia.Media; |
|
||||
using Avalonia.Platform; |
|
||||
using Avalonia.Rendering.SceneGraph; |
|
||||
using Avalonia.Utilities; |
|
||||
using Avalonia.Media.Imaging; |
|
||||
|
|
||||
namespace Avalonia.Benchmarks |
|
||||
{ |
|
||||
internal class NullDrawingContextImpl : IDrawingContextImpl |
|
||||
{ |
|
||||
public void Dispose() |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public Matrix Transform { get; set; } |
|
||||
|
|
||||
public RenderOptions RenderOptions { get; set; } |
|
||||
|
|
||||
public void Clear(Color color) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public void DrawBitmap(IRef<IBitmapImpl> source, double opacity, Rect sourceRect, Rect destRect) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public void DrawBitmap(IRef<IBitmapImpl> source, IBrush opacityMask, Rect opacityMaskRect, Rect destRect) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public void DrawLine(IPen pen, Point p1, Point p2) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public void DrawGeometry(IBrush brush, IPen pen, IGeometryImpl geometry) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public void DrawRectangle(IBrush brush, IPen pen, RoundedRect rect, BoxShadows boxShadows = default) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public void DrawEllipse(IBrush brush, IPen pen, Rect rect) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public void DrawGlyphRun(IBrush foreground, IRef<IGlyphRunImpl> glyphRun) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public IDrawingContextLayerImpl CreateLayer(Size size) |
|
||||
{ |
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
public void PushClip(Rect clip) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public void PushClip(RoundedRect clip) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public void PopClip() |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public void PushOpacity(double opacity, Rect bounds) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public void PopOpacity() |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public void PushOpacityMask(IBrush mask, Rect bounds) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public void PopOpacityMask() |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public void PushGeometryClip(IGeometryImpl clip) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public void PopGeometryClip() |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public void PushBitmapBlendMode(BitmapBlendingMode blendingMode) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public void PopBitmapBlendMode() |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public void Custom(ICustomDrawOperation custom) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public object GetFeature(Type t) => null; |
|
||||
} |
|
||||
} |
|
||||
@ -1,149 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.IO; |
|
||||
using Avalonia.Media; |
|
||||
using Avalonia.Platform; |
|
||||
using Avalonia.UnitTests; |
|
||||
using Avalonia.Media.Imaging; |
|
||||
using Avalonia.Media.TextFormatting; |
|
||||
using Microsoft.Diagnostics.Runtime; |
|
||||
|
|
||||
namespace Avalonia.Benchmarks |
|
||||
{ |
|
||||
internal class NullRenderingPlatform : IPlatformRenderInterface, IPlatformRenderInterfaceContext |
|
||||
{ |
|
||||
public IGeometryImpl CreateEllipseGeometry(Rect rect) |
|
||||
{ |
|
||||
return new MockStreamGeometryImpl(); |
|
||||
} |
|
||||
|
|
||||
public IGeometryImpl CreateLineGeometry(Point p1, Point p2) |
|
||||
{ |
|
||||
return new MockStreamGeometryImpl(); |
|
||||
} |
|
||||
|
|
||||
public IGeometryImpl CreateRectangleGeometry(Rect rect) |
|
||||
{ |
|
||||
return new MockStreamGeometryImpl(); |
|
||||
} |
|
||||
|
|
||||
public IStreamGeometryImpl CreateStreamGeometry() |
|
||||
{ |
|
||||
return new MockStreamGeometryImpl(); |
|
||||
} |
|
||||
|
|
||||
public IGeometryImpl CreateGeometryGroup(FillRule fillRule, IReadOnlyList<IGeometryImpl> children) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IGeometryImpl CreateCombinedGeometry(GeometryCombineMode combineMode, IGeometryImpl g1, IGeometryImpl g2) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IRenderTarget CreateRenderTarget(IEnumerable<object> surfaces) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public bool IsLost => false; |
|
||||
|
|
||||
public object TryGetFeature(Type featureType) => null; |
|
||||
|
|
||||
public IRenderTargetBitmapImpl CreateRenderTargetBitmap(PixelSize size, Vector dpi) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IWriteableBitmapImpl CreateWriteableBitmap(PixelSize size, Vector dpi, PixelFormat format, AlphaFormat alphaFormat) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IBitmapImpl LoadBitmap(string fileName) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IBitmapImpl LoadBitmap(Stream stream) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IWriteableBitmapImpl LoadWriteableBitmapToWidth(Stream stream, int width, |
|
||||
BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IWriteableBitmapImpl LoadWriteableBitmapToHeight(Stream stream, int height, |
|
||||
BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IWriteableBitmapImpl LoadWriteableBitmap(string fileName) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IWriteableBitmapImpl LoadWriteableBitmap(Stream stream) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IBitmapImpl LoadBitmap(PixelFormat format, AlphaFormat alphaFormat, IntPtr data, PixelSize size, Vector dpi, int stride) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IBitmapImpl LoadBitmapToWidth(Stream stream, int width, BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IBitmapImpl LoadBitmapToHeight(Stream stream, int height, BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IBitmapImpl ResizeBitmap(IBitmapImpl bitmapImpl, PixelSize destinationSize, BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IFontManagerImpl CreateFontManager() |
|
||||
{ |
|
||||
return new MockFontManagerImpl(); |
|
||||
} |
|
||||
|
|
||||
public IGeometryImpl BuildGlyphRunGeometry(GlyphRun glyphRun) |
|
||||
{ |
|
||||
return new MockStreamGeometryImpl(); |
|
||||
} |
|
||||
|
|
||||
public IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize, |
|
||||
IReadOnlyList<GlyphInfo> glyphInfos, Point baselineOrigin, Rect bounds) |
|
||||
{ |
|
||||
return new MockGlyphRun(glyphTypeface, fontRenderingEmSize, baselineOrigin, bounds); |
|
||||
} |
|
||||
|
|
||||
public IPlatformRenderInterfaceContext CreateBackendContext(IPlatformGraphicsContext graphicsContext) |
|
||||
{ |
|
||||
return this; |
|
||||
} |
|
||||
|
|
||||
public bool SupportsIndividualRoundRects => true; |
|
||||
|
|
||||
public AlphaFormat DefaultAlphaFormat => AlphaFormat.Premul; |
|
||||
|
|
||||
public PixelFormat DefaultPixelFormat => PixelFormat.Rgba8888; |
|
||||
public bool IsSupportedBitmapPixelFormat(PixelFormat format) => true; |
|
||||
|
|
||||
public void Dispose() |
|
||||
{ |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,27 +0,0 @@ |
|||||
using System; |
|
||||
using System.Reactive.Disposables; |
|
||||
using System.Threading; |
|
||||
using Avalonia.Platform; |
|
||||
using Avalonia.Threading; |
|
||||
|
|
||||
namespace Avalonia.Benchmarks |
|
||||
{ |
|
||||
internal class NullThreadingPlatform : IDispatcherImpl |
|
||||
{ |
|
||||
public void Signal() |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public void UpdateTimer(long? dueTimeInMs) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public bool CurrentThreadIsLoopThread => true; |
|
||||
|
|
||||
#pragma warning disable CS0067
|
|
||||
public event Action Signaled; |
|
||||
public event Action Timer; |
|
||||
public long Now => 0; |
|
||||
#pragma warning restore CS0067
|
|
||||
} |
|
||||
} |
|
||||
@ -1,62 +0,0 @@ |
|||||
using System; |
|
||||
using System.Threading; |
|
||||
using System.Threading.Tasks; |
|
||||
using Avalonia.Threading; |
|
||||
|
|
||||
namespace Avalonia.UnitTests |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Immediately invokes dispatched jobs on the current thread.
|
|
||||
/// </summary>
|
|
||||
public class ImmediateDispatcher : IDispatcher |
|
||||
{ |
|
||||
/// <inheritdoc/>
|
|
||||
public bool CheckAccess() |
|
||||
{ |
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public void Post(Action action, DispatcherPriority priority) |
|
||||
{ |
|
||||
action(); |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public void Post(SendOrPostCallback action, object arg, DispatcherPriority priority) |
|
||||
{ |
|
||||
action(arg); |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public Task InvokeAsync(Action action, DispatcherPriority priority) |
|
||||
{ |
|
||||
action(); |
|
||||
return Task.CompletedTask; |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public Task<TResult> InvokeAsync<TResult>(Func<TResult> function, DispatcherPriority priority) |
|
||||
{ |
|
||||
var result = function(); |
|
||||
return Task.FromResult(result); |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public Task InvokeAsync(Func<Task> function, DispatcherPriority priority) |
|
||||
{ |
|
||||
return function(); |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public Task<TResult> InvokeAsync<TResult>(Func<Task<TResult>> function, DispatcherPriority priority) |
|
||||
{ |
|
||||
return function(); |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public void VerifyAccess() |
|
||||
{ |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,63 +0,0 @@ |
|||||
using System.Diagnostics.CodeAnalysis; |
|
||||
using System.Globalization; |
|
||||
using System.IO; |
|
||||
using Avalonia.Media; |
|
||||
using Avalonia.Platform; |
|
||||
|
|
||||
namespace Avalonia.UnitTests |
|
||||
{ |
|
||||
public class MockFontManagerImpl : IFontManagerImpl |
|
||||
{ |
|
||||
private readonly string _defaultFamilyName; |
|
||||
|
|
||||
public MockFontManagerImpl(string defaultFamilyName = "Default") |
|
||||
{ |
|
||||
_defaultFamilyName = defaultFamilyName; |
|
||||
} |
|
||||
|
|
||||
public int TryCreateGlyphTypefaceCount { get; private set; } |
|
||||
|
|
||||
public string GetDefaultFontFamilyName() |
|
||||
{ |
|
||||
return _defaultFamilyName; |
|
||||
} |
|
||||
|
|
||||
string[] IFontManagerImpl.GetInstalledFontFamilyNames(bool checkForUpdates) |
|
||||
{ |
|
||||
return new[] { _defaultFamilyName }; |
|
||||
} |
|
||||
|
|
||||
public bool TryMatchCharacter(int codepoint, FontStyle fontStyle, FontWeight fontWeight, |
|
||||
FontStretch fontStretch, |
|
||||
CultureInfo culture, out Typeface fontKey) |
|
||||
{ |
|
||||
fontKey = new Typeface(_defaultFamilyName); |
|
||||
|
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
public virtual bool TryCreateGlyphTypeface(string familyName, FontStyle style, FontWeight weight, |
|
||||
FontStretch stretch, [NotNullWhen(true)] out IGlyphTypeface glyphTypeface) |
|
||||
{ |
|
||||
glyphTypeface = null; |
|
||||
|
|
||||
TryCreateGlyphTypefaceCount++; |
|
||||
|
|
||||
if (familyName == "Unknown") |
|
||||
{ |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
glyphTypeface = new MockGlyphTypeface(); |
|
||||
|
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
public virtual bool TryCreateGlyphTypeface(Stream stream, out IGlyphTypeface glyphTypeface) |
|
||||
{ |
|
||||
glyphTypeface = new MockGlyphTypeface(); |
|
||||
|
|
||||
return true; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,34 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using Avalonia.Media; |
|
||||
using Avalonia.Platform; |
|
||||
|
|
||||
namespace Avalonia.UnitTests |
|
||||
{ |
|
||||
public class MockGlyphRun : IGlyphRunImpl |
|
||||
{ |
|
||||
public MockGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize, Point baselineOrigin, Rect bounds) |
|
||||
{ |
|
||||
GlyphTypeface = glyphTypeface; |
|
||||
FontRenderingEmSize = fontRenderingEmSize; |
|
||||
BaselineOrigin = baselineOrigin; |
|
||||
Bounds =bounds; |
|
||||
} |
|
||||
|
|
||||
public IGlyphTypeface GlyphTypeface { get; } |
|
||||
|
|
||||
public double FontRenderingEmSize { get; } |
|
||||
|
|
||||
public Point BaselineOrigin { get; } |
|
||||
|
|
||||
public Rect Bounds { get; } |
|
||||
|
|
||||
public void Dispose() |
|
||||
{ |
|
||||
|
|
||||
} |
|
||||
|
|
||||
public IReadOnlyList<float> GetIntersections(float lowerLimit, float upperLimit) |
|
||||
=> Array.Empty<float>(); |
|
||||
} |
|
||||
} |
|
||||
@ -1,81 +0,0 @@ |
|||||
using System; |
|
||||
using Avalonia.Media; |
|
||||
|
|
||||
namespace Avalonia.UnitTests |
|
||||
{ |
|
||||
public class MockGlyphTypeface : IGlyphTypeface |
|
||||
{ |
|
||||
public FontMetrics Metrics => new FontMetrics |
|
||||
{ |
|
||||
DesignEmHeight = 10, |
|
||||
Ascent = 2, |
|
||||
Descent = 10, |
|
||||
IsFixedPitch = true |
|
||||
}; |
|
||||
|
|
||||
public int GlyphCount => 1337; |
|
||||
|
|
||||
public FontSimulations FontSimulations => throw new NotImplementedException(); |
|
||||
|
|
||||
public string FamilyName => "$Default"; |
|
||||
|
|
||||
public FontWeight Weight { get; } |
|
||||
|
|
||||
public FontStyle Style { get; } |
|
||||
|
|
||||
public FontStretch Stretch { get; } |
|
||||
|
|
||||
public ushort GetGlyph(uint codepoint) |
|
||||
{ |
|
||||
return (ushort)codepoint; |
|
||||
} |
|
||||
|
|
||||
public ushort[] GetGlyphs(ReadOnlySpan<uint> codepoints) |
|
||||
{ |
|
||||
return new ushort[codepoints.Length]; |
|
||||
} |
|
||||
|
|
||||
public int GetGlyphAdvance(ushort glyph) |
|
||||
{ |
|
||||
return 8; |
|
||||
} |
|
||||
|
|
||||
public bool TryGetGlyph(uint codepoint, out ushort glyph) |
|
||||
{ |
|
||||
glyph = 8; |
|
||||
|
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
public int[] GetGlyphAdvances(ReadOnlySpan<ushort> glyphs) |
|
||||
{ |
|
||||
var advances = new int[glyphs.Length]; |
|
||||
|
|
||||
for (var i = 0; i < advances.Length; i++) |
|
||||
{ |
|
||||
advances[i] = 8; |
|
||||
} |
|
||||
|
|
||||
return advances; |
|
||||
} |
|
||||
|
|
||||
public void Dispose() { } |
|
||||
|
|
||||
public bool TryGetTable(uint tag, out byte[] table) |
|
||||
{ |
|
||||
table = null; |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
public bool TryGetGlyphMetrics(ushort glyph, out GlyphMetrics metrics) |
|
||||
{ |
|
||||
metrics = new GlyphMetrics |
|
||||
{ |
|
||||
Width = 10, |
|
||||
Height = 10 |
|
||||
}; |
|
||||
|
|
||||
return true; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,174 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.IO; |
|
||||
using Avalonia.Media; |
|
||||
using Avalonia.Platform; |
|
||||
using Avalonia.Media.Imaging; |
|
||||
using Avalonia.Media.TextFormatting; |
|
||||
using Moq; |
|
||||
|
|
||||
namespace Avalonia.UnitTests |
|
||||
{ |
|
||||
public class MockPlatformRenderInterface : IPlatformRenderInterface, IPlatformRenderInterfaceContext |
|
||||
{ |
|
||||
public IGeometryImpl CreateEllipseGeometry(Rect rect) |
|
||||
{ |
|
||||
return Mock.Of<IGeometryImpl>(); |
|
||||
} |
|
||||
|
|
||||
public IGeometryImpl CreateLineGeometry(Point p1, Point p2) |
|
||||
{ |
|
||||
return Mock.Of<IGeometryImpl>(); |
|
||||
} |
|
||||
|
|
||||
public IGeometryImpl CreateRectangleGeometry(Rect rect) |
|
||||
{ |
|
||||
return Mock.Of<IGeometryImpl>(x => x.Bounds == rect); |
|
||||
} |
|
||||
|
|
||||
class MockRenderTarget : IRenderTarget |
|
||||
{ |
|
||||
public void Dispose() |
|
||||
{ |
|
||||
|
|
||||
} |
|
||||
|
|
||||
public IDrawingContextImpl CreateDrawingContext() |
|
||||
{ |
|
||||
var m = new Mock<IDrawingContextImpl>(); |
|
||||
m.Setup(c => c.CreateLayer(It.IsAny<Size>())) |
|
||||
.Returns(() => |
|
||||
{ |
|
||||
var r = new Mock<IDrawingContextLayerImpl>(); |
|
||||
r.Setup(r => r.CreateDrawingContext()) |
|
||||
.Returns(CreateDrawingContext()); |
|
||||
return r.Object; |
|
||||
} |
|
||||
); |
|
||||
return m.Object; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
public bool IsCorrupted => false; |
|
||||
} |
|
||||
|
|
||||
public IRenderTarget CreateRenderTarget(IEnumerable<object> surfaces) |
|
||||
{ |
|
||||
return new MockRenderTarget(); |
|
||||
} |
|
||||
|
|
||||
public bool IsLost => false; |
|
||||
|
|
||||
public object TryGetFeature(Type featureType) => null; |
|
||||
|
|
||||
public IRenderTargetBitmapImpl CreateRenderTargetBitmap(PixelSize size, Vector dpi) |
|
||||
{ |
|
||||
return Mock.Of<IRenderTargetBitmapImpl>(); |
|
||||
} |
|
||||
|
|
||||
public IStreamGeometryImpl CreateStreamGeometry() |
|
||||
{ |
|
||||
return new MockStreamGeometryImpl(); |
|
||||
} |
|
||||
|
|
||||
public IGeometryImpl CreateGeometryGroup(FillRule fillRule, IReadOnlyList<IGeometryImpl> children) |
|
||||
{ |
|
||||
return Mock.Of<IGeometryImpl>(); |
|
||||
} |
|
||||
|
|
||||
public IGeometryImpl CreateCombinedGeometry(GeometryCombineMode combineMode, IGeometryImpl g1, IGeometryImpl g2) |
|
||||
{ |
|
||||
return Mock.Of<IGeometryImpl>(); |
|
||||
} |
|
||||
|
|
||||
public IWriteableBitmapImpl CreateWriteableBitmap( |
|
||||
PixelSize size, |
|
||||
Vector dpi, |
|
||||
PixelFormat format, |
|
||||
AlphaFormat alphaFormat) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IBitmapImpl LoadBitmap(Stream stream) |
|
||||
{ |
|
||||
return Mock.Of<IBitmapImpl>(); |
|
||||
} |
|
||||
|
|
||||
public IWriteableBitmapImpl LoadWriteableBitmapToWidth(Stream stream, int width, |
|
||||
BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IWriteableBitmapImpl LoadWriteableBitmapToHeight(Stream stream, int height, |
|
||||
BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IWriteableBitmapImpl LoadWriteableBitmap(string fileName) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IWriteableBitmapImpl LoadWriteableBitmap(Stream stream) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IBitmapImpl LoadBitmap(string fileName) |
|
||||
{ |
|
||||
return Mock.Of<IBitmapImpl>(); |
|
||||
} |
|
||||
|
|
||||
public IBitmapImpl LoadBitmapToWidth(Stream stream, int width, BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality) |
|
||||
{ |
|
||||
return Mock.Of<IBitmapImpl>(); |
|
||||
} |
|
||||
|
|
||||
public IBitmapImpl LoadBitmapToHeight(Stream stream, int height, BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality) |
|
||||
{ |
|
||||
return Mock.Of<IBitmapImpl>(); |
|
||||
} |
|
||||
|
|
||||
public IBitmapImpl ResizeBitmap(IBitmapImpl bitmapImpl, PixelSize destinationSize, BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality) |
|
||||
{ |
|
||||
return Mock.Of<IBitmapImpl>(); |
|
||||
} |
|
||||
|
|
||||
public IBitmapImpl LoadBitmap( |
|
||||
PixelFormat format, |
|
||||
AlphaFormat alphaFormat, |
|
||||
IntPtr data, |
|
||||
PixelSize size, |
|
||||
Vector dpi, |
|
||||
int stride) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize, IReadOnlyList<GlyphInfo> glyphInfos, Point baselineOrigin, Rect bounds) |
|
||||
{ |
|
||||
return new MockGlyphRun(glyphTypeface, fontRenderingEmSize, baselineOrigin, bounds); |
|
||||
} |
|
||||
|
|
||||
public IPlatformRenderInterfaceContext CreateBackendContext(IPlatformGraphicsContext graphicsContext) => this; |
|
||||
|
|
||||
public IGeometryImpl BuildGlyphRunGeometry(GlyphRun glyphRun) |
|
||||
{ |
|
||||
return Mock.Of<IGeometryImpl>(); |
|
||||
} |
|
||||
|
|
||||
public bool SupportsIndividualRoundRects { get; set; } |
|
||||
|
|
||||
public AlphaFormat DefaultAlphaFormat => AlphaFormat.Premul; |
|
||||
|
|
||||
public PixelFormat DefaultPixelFormat => PixelFormat.Rgba8888; |
|
||||
public bool IsSupportedBitmapPixelFormat(PixelFormat format) => true; |
|
||||
|
|
||||
public void Dispose() |
|
||||
{ |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,179 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using Avalonia.Media; |
|
||||
using Avalonia.Platform; |
|
||||
|
|
||||
namespace Avalonia.UnitTests |
|
||||
{ |
|
||||
public class MockStreamGeometryImpl : IStreamGeometryImpl, ITransformedGeometryImpl |
|
||||
{ |
|
||||
private MockStreamGeometryContext _context; |
|
||||
|
|
||||
public MockStreamGeometryImpl() |
|
||||
{ |
|
||||
Transform = Matrix.Identity; |
|
||||
_context = new MockStreamGeometryContext(); |
|
||||
} |
|
||||
|
|
||||
public MockStreamGeometryImpl(Matrix transform) |
|
||||
{ |
|
||||
Transform = transform; |
|
||||
_context = new MockStreamGeometryContext(); |
|
||||
} |
|
||||
|
|
||||
private MockStreamGeometryImpl(Matrix transform, MockStreamGeometryContext context) |
|
||||
{ |
|
||||
Transform = transform; |
|
||||
_context = context; |
|
||||
} |
|
||||
|
|
||||
public IGeometryImpl SourceGeometry { get; } |
|
||||
|
|
||||
public Rect Bounds => _context.CalculateBounds(); |
|
||||
|
|
||||
public double ContourLength { get; } |
|
||||
|
|
||||
public Matrix Transform { get; } |
|
||||
|
|
||||
public IStreamGeometryImpl Clone() |
|
||||
{ |
|
||||
return this; |
|
||||
} |
|
||||
|
|
||||
public void Dispose() |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public bool FillContains(Point point) |
|
||||
{ |
|
||||
return _context.FillContains(point); |
|
||||
} |
|
||||
|
|
||||
public bool StrokeContains(IPen pen, Point point) |
|
||||
{ |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
public Rect GetRenderBounds(IPen pen) => Bounds; |
|
||||
|
|
||||
public IGeometryImpl Intersect(IGeometryImpl geometry) |
|
||||
{ |
|
||||
return new MockStreamGeometryImpl(Transform); |
|
||||
} |
|
||||
|
|
||||
public IStreamGeometryContextImpl Open() |
|
||||
{ |
|
||||
return _context; |
|
||||
} |
|
||||
|
|
||||
public ITransformedGeometryImpl WithTransform(Matrix transform) |
|
||||
{ |
|
||||
return new MockStreamGeometryImpl(transform, _context); |
|
||||
} |
|
||||
|
|
||||
public bool TryGetPointAtDistance(double distance, out Point point) |
|
||||
{ |
|
||||
point = new Point(); |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
public bool TryGetPointAndTangentAtDistance(double distance, out Point point, out Point tangent) |
|
||||
{ |
|
||||
point = new Point(); |
|
||||
tangent = new Point(); |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
public bool TryGetSegment(double startDistance, double stopDistance, bool startOnBeginFigure, out IGeometryImpl segmentGeometry) |
|
||||
{ |
|
||||
segmentGeometry = null; |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
class MockStreamGeometryContext : IStreamGeometryContextImpl |
|
||||
{ |
|
||||
private List<Point> points = new List<Point>(); |
|
||||
public void ArcTo(Point point, Size size, double rotationAngle, bool isLargeArc, SweepDirection sweepDirection) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public void BeginFigure(Point startPoint, bool isFilled) |
|
||||
{ |
|
||||
points.Add(startPoint); |
|
||||
} |
|
||||
|
|
||||
public Rect CalculateBounds() |
|
||||
{ |
|
||||
var left = double.MaxValue; |
|
||||
var right = double.MinValue; |
|
||||
var top = double.MaxValue; |
|
||||
var bottom = double.MinValue; |
|
||||
|
|
||||
foreach (var p in points) |
|
||||
{ |
|
||||
left = Math.Min(p.X, left); |
|
||||
right = Math.Max(p.X, right); |
|
||||
top = Math.Min(p.Y, top); |
|
||||
bottom = Math.Max(p.Y, bottom); |
|
||||
} |
|
||||
|
|
||||
return new Rect(new Point(left, top), new Point(right, bottom)); |
|
||||
} |
|
||||
|
|
||||
public void CubicBezierTo(Point point1, Point point2, Point point3) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public void Dispose() |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public void EndFigure(bool isClosed) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public void LineTo(Point point) |
|
||||
{ |
|
||||
points.Add(point); |
|
||||
} |
|
||||
|
|
||||
public void QuadraticBezierTo(Point control, Point endPoint) |
|
||||
{ |
|
||||
throw new NotImplementedException(); |
|
||||
} |
|
||||
|
|
||||
public void SetFillRule(FillRule fillRule) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public bool FillContains(Point point) |
|
||||
{ |
|
||||
// Use the algorithm from https://www.blackpawn.com/texts/pointinpoly/default.html
|
|
||||
// to determine if the point is in the geometry (since it will always be convex in this situation)
|
|
||||
for (int i = 0; i < points.Count; i++) |
|
||||
{ |
|
||||
var a = points[i]; |
|
||||
var b = points[(i + 1) % points.Count]; |
|
||||
var c = points[(i + 2) % points.Count]; |
|
||||
|
|
||||
Vector v0 = c - a; |
|
||||
Vector v1 = b - a; |
|
||||
Vector v2 = point - a; |
|
||||
|
|
||||
var dot00 = v0 * v0; |
|
||||
var dot01 = v0 * v1; |
|
||||
var dot02 = v0 * v2; |
|
||||
var dot11 = v1 * v1; |
|
||||
var dot12 = v1 * v2; |
|
||||
|
|
||||
|
|
||||
var invDenom = 1 / (dot00 * dot11 - dot01 * dot01); |
|
||||
var u = (dot11 * dot02 - dot01 * dot12) * invDenom; |
|
||||
var v = (dot00 * dot12 - dot01 * dot02) * invDenom; |
|
||||
if ((u >= 0) && (v >= 0) && (u + v < 1)) return true; |
|
||||
} |
|
||||
return false; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,38 +0,0 @@ |
|||||
using System; |
|
||||
using Avalonia.Media.TextFormatting; |
|
||||
using Avalonia.Media.TextFormatting.Unicode; |
|
||||
using Avalonia.Platform; |
|
||||
|
|
||||
namespace Avalonia.UnitTests |
|
||||
{ |
|
||||
public class MockTextShaperImpl : ITextShaperImpl |
|
||||
{ |
|
||||
public ShapedBuffer ShapeText(ReadOnlyMemory<char> text, TextShaperOptions options) |
|
||||
{ |
|
||||
var typeface = options.Typeface; |
|
||||
var fontRenderingEmSize = options.FontRenderingEmSize; |
|
||||
var bidiLevel = options.BidiLevel; |
|
||||
var shapedBuffer = new ShapedBuffer(text, text.Length, typeface, fontRenderingEmSize, bidiLevel); |
|
||||
var textSpan = text.Span; |
|
||||
var textStartIndex = TextTestHelper.GetStartCharIndex(text); |
|
||||
|
|
||||
for (var i = 0; i < shapedBuffer.Length;) |
|
||||
{ |
|
||||
var glyphCluster = i + textStartIndex; |
|
||||
|
|
||||
var codepoint = Codepoint.ReadAt(textSpan, i, out var count); |
|
||||
|
|
||||
var glyphIndex = typeface.GetGlyph(codepoint); |
|
||||
|
|
||||
for (var j = 0; j < count; ++j) |
|
||||
{ |
|
||||
shapedBuffer[i + j] = new GlyphInfo(glyphIndex, glyphCluster, 10); |
|
||||
} |
|
||||
|
|
||||
i += count; |
|
||||
} |
|
||||
|
|
||||
return shapedBuffer; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,15 +0,0 @@ |
|||||
using System; |
|
||||
using System.Runtime.InteropServices; |
|
||||
|
|
||||
namespace Avalonia.UnitTests |
|
||||
{ |
|
||||
public static class TextTestHelper |
|
||||
{ |
|
||||
public static int GetStartCharIndex(ReadOnlyMemory<char> text) |
|
||||
{ |
|
||||
if (!MemoryMarshal.TryGetString(text, out _, out var start, out _)) |
|
||||
throw new InvalidOperationException("text memory should have been a string"); |
|
||||
return start; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue