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