// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System.Numerics;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.PublicApi.Tests;
///
/// Verifies that representation-aware pixel operations can be implemented outside the ImageSharp assembly.
///
public class PixelOperationsExtensibilityTests
{
///
/// Verifies that an external subclass can override and invoke every representation-aware hook.
///
[Fact]
public void PixelOperationsExposesAllRepresentationHooksToExternalSubclasses()
{
ExternalRgba32PixelOperations operations = new();
operations.InvokeRepresentationHooks();
Assert.Equal(RepresentationHooks.All, operations.InvokedHooks);
}
///
/// Verifies that an external subclass can override and invoke every representation-aware hook.
///
[Fact]
public void AssociatedAlphaPixelOperationsExposesAllRepresentationHooksToExternalSubclasses()
{
ExternalRgba32PPixelOperations operations = new();
operations.InvokeRepresentationHooks();
Assert.Equal(RepresentationHooks.All, operations.InvokedHooks);
}
[Flags]
private enum RepresentationHooks
{
None = 0,
ToUnassociatedVector4 = 1 << 0,
ToAssociatedVector4 = 1 << 1,
ToUnassociatedScaledVector4 = 1 << 2,
ToAssociatedScaledVector4 = 1 << 3,
FromUnassociatedVector4Destructive = 1 << 4,
FromAssociatedVector4Destructive = 1 << 5,
FromUnassociatedScaledVector4Destructive = 1 << 6,
FromAssociatedScaledVector4Destructive = 1 << 7,
All = ToUnassociatedVector4
| ToAssociatedVector4
| ToUnassociatedScaledVector4
| ToAssociatedScaledVector4
| FromUnassociatedVector4Destructive
| FromAssociatedVector4Destructive
| FromUnassociatedScaledVector4Destructive
| FromAssociatedScaledVector4Destructive
}
///
/// Exercises the representation-aware hooks inherited directly from .
///
private sealed class ExternalRgba32PixelOperations : PixelOperations
{
///
/// Gets the hooks invoked through this external subclass.
///
public RepresentationHooks InvokedHooks { get; private set; }
///
/// Invokes every representation-aware operation exposed to derived classes.
///
public void InvokeRepresentationHooks()
{
// Empty spans isolate accessibility and virtual dispatch; conversion behavior is covered by the pixel-operation test suite.
this.ToUnassociatedVector4(Configuration.Default, ReadOnlySpan.Empty, Span.Empty);
this.ToAssociatedVector4(Configuration.Default, ReadOnlySpan.Empty, Span.Empty);
this.ToUnassociatedScaledVector4(Configuration.Default, ReadOnlySpan.Empty, Span.Empty);
this.ToAssociatedScaledVector4(Configuration.Default, ReadOnlySpan.Empty, Span.Empty);
this.FromUnassociatedVector4Destructive(Configuration.Default, Span.Empty, Span.Empty);
this.FromAssociatedVector4Destructive(Configuration.Default, Span.Empty, Span.Empty);
this.FromUnassociatedScaledVector4Destructive(Configuration.Default, Span.Empty, Span.Empty);
this.FromAssociatedScaledVector4Destructive(Configuration.Default, Span.Empty, Span.Empty);
}
///
protected override void ToUnassociatedVector4(Configuration configuration, ReadOnlySpan source, Span destination) => this.InvokedHooks |= RepresentationHooks.ToUnassociatedVector4;
///
protected override void ToAssociatedVector4(Configuration configuration, ReadOnlySpan source, Span destination) => this.InvokedHooks |= RepresentationHooks.ToAssociatedVector4;
///
protected override void ToUnassociatedScaledVector4(Configuration configuration, ReadOnlySpan source, Span destination) => this.InvokedHooks |= RepresentationHooks.ToUnassociatedScaledVector4;
///
protected override void ToAssociatedScaledVector4(Configuration configuration, ReadOnlySpan source, Span destination) => this.InvokedHooks |= RepresentationHooks.ToAssociatedScaledVector4;
///
protected override void FromUnassociatedVector4Destructive(Configuration configuration, Span source, Span destination) => this.InvokedHooks |= RepresentationHooks.FromUnassociatedVector4Destructive;
///
protected override void FromAssociatedVector4Destructive(Configuration configuration, Span source, Span destination) => this.InvokedHooks |= RepresentationHooks.FromAssociatedVector4Destructive;
///
protected override void FromUnassociatedScaledVector4Destructive(Configuration configuration, Span source, Span destination) => this.InvokedHooks |= RepresentationHooks.FromUnassociatedScaledVector4Destructive;
///
protected override void FromAssociatedScaledVector4Destructive(Configuration configuration, Span source, Span destination) => this.InvokedHooks |= RepresentationHooks.FromAssociatedScaledVector4Destructive;
}
///
/// Exercises the representation-aware hooks inherited through .
///
private sealed class ExternalRgba32PPixelOperations : AssociatedAlphaPixelOperations
{
///
/// Gets the hooks invoked through this external subclass.
///
public RepresentationHooks InvokedHooks { get; private set; }
///
/// Invokes every representation-aware operation exposed to derived classes.
///
public void InvokeRepresentationHooks()
{
// Empty spans isolate accessibility and virtual dispatch; conversion behavior is covered by the pixel-operation test suite.
this.ToUnassociatedVector4(Configuration.Default, ReadOnlySpan.Empty, Span.Empty);
this.ToAssociatedVector4(Configuration.Default, ReadOnlySpan.Empty, Span.Empty);
this.ToUnassociatedScaledVector4(Configuration.Default, ReadOnlySpan.Empty, Span.Empty);
this.ToAssociatedScaledVector4(Configuration.Default, ReadOnlySpan.Empty, Span.Empty);
this.FromUnassociatedVector4Destructive(Configuration.Default, Span.Empty, Span.Empty);
this.FromAssociatedVector4Destructive(Configuration.Default, Span.Empty, Span.Empty);
this.FromUnassociatedScaledVector4Destructive(Configuration.Default, Span.Empty, Span.Empty);
this.FromAssociatedScaledVector4Destructive(Configuration.Default, Span.Empty, Span.Empty);
}
///
protected override void ToUnassociatedVector4(Configuration configuration, ReadOnlySpan source, Span destination) => this.InvokedHooks |= RepresentationHooks.ToUnassociatedVector4;
///
protected override void ToAssociatedVector4(Configuration configuration, ReadOnlySpan source, Span destination) => this.InvokedHooks |= RepresentationHooks.ToAssociatedVector4;
///
protected override void ToUnassociatedScaledVector4(Configuration configuration, ReadOnlySpan source, Span destination) => this.InvokedHooks |= RepresentationHooks.ToUnassociatedScaledVector4;
///
protected override void ToAssociatedScaledVector4(Configuration configuration, ReadOnlySpan source, Span destination) => this.InvokedHooks |= RepresentationHooks.ToAssociatedScaledVector4;
///
protected override void FromUnassociatedVector4Destructive(Configuration configuration, Span source, Span destination) => this.InvokedHooks |= RepresentationHooks.FromUnassociatedVector4Destructive;
///
protected override void FromAssociatedVector4Destructive(Configuration configuration, Span source, Span destination) => this.InvokedHooks |= RepresentationHooks.FromAssociatedVector4Destructive;
///
protected override void FromUnassociatedScaledVector4Destructive(Configuration configuration, Span source, Span destination) => this.InvokedHooks |= RepresentationHooks.FromUnassociatedScaledVector4Destructive;
///
protected override void FromAssociatedScaledVector4Destructive(Configuration configuration, Span source, Span destination) => this.InvokedHooks |= RepresentationHooks.FromAssociatedScaledVector4Destructive;
}
}