diff --git a/src/ImageSharp.Drawing/Processing/Drawing/Brushes/GradientBrushes/GradientBrushBase{TPixel}.cs b/src/ImageSharp.Drawing/Processing/Drawing/Brushes/GradientBrushes/GradientBrushBase{TPixel}.cs index d0a1ef1c24..061023428b 100644 --- a/src/ImageSharp.Drawing/Processing/Drawing/Brushes/GradientBrushes/GradientBrushBase{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/Drawing/Brushes/GradientBrushes/GradientBrushBase{TPixel}.cs @@ -121,7 +121,7 @@ namespace SixLabors.ImageSharp.Processing.Drawing.Brushes.GradientBrushes float onLocalGradient = (positionOnCompleteGradient - from.Ratio) / to.Ratio; // TODO: this should be changeble for different gradienting functions - Vector4 result = PorterDuffFunctions.Normal( + Vector4 result = PorterDuffFunctions.Normal_SrcOver( fromAsVector, toAsVector, onLocalGradient); diff --git a/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.cs b/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.cs index 6828f11dcc..c5bed2b270 100644 --- a/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.cs @@ -1,4 +1,11 @@ -// Copyright (c) Six Labors and contributors. + + + + + + + +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. // @@ -24,17 +31,258 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders where TPixel : struct, IPixel { - internal class Normal : PixelBlender + + internal class Normal_Src : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Normal_Src Instance { get; } = new Normal_Src(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Normal_Src(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Normal_Src(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Multiply_Src : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Multiply_Src Instance { get; } = new Multiply_Src(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Multiply_Src(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Multiply_Src(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Add_Src : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Add_Src Instance { get; } = new Add_Src(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Add_Src(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Add_Src(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Subtract_Src : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Subtract_Src Instance { get; } = new Subtract_Src(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Subtract_Src(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Subtract_Src(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Screen_Src : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Screen_Src Instance { get; } = new Screen_Src(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Screen_Src(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Screen_Src(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Darken_Src : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Darken_Src Instance { get; } = new Darken_Src(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Darken_Src(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Darken_Src(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Lighten_Src : PixelBlender { /// /// Gets the static instance of this blender. /// - public static Normal Instance { get; } = new Normal(); + public static Lighten_Src Instance { get; } = new Lighten_Src(); /// public override TPixel Blend(TPixel background, TPixel source, float amount) { - return PorterDuffFunctions.Normal(background, source, amount); + return PorterDuffFunctions.Lighten_Src(background, source, amount); } /// @@ -55,7 +303,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders for (int i = 0; i < destination.Length; i++) { - destinationSpan[i] = PorterDuffFunctions.Normal(backgroundSpan[i], sourceSpan[i], amount[i]); + destinationSpan[i] = PorterDuffFunctions.Lighten_Src(backgroundSpan[i], sourceSpan[i], amount[i]); } PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); @@ -63,17 +311,18 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } } - internal class Multiply : PixelBlender + + internal class Overlay_Src : PixelBlender { /// /// Gets the static instance of this blender. /// - public static Multiply Instance { get; } = new Multiply(); + public static Overlay_Src Instance { get; } = new Overlay_Src(); /// public override TPixel Blend(TPixel background, TPixel source, float amount) { - return PorterDuffFunctions.Multiply(background, source, amount); + return PorterDuffFunctions.Overlay_Src(background, source, amount); } /// @@ -94,7 +343,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders for (int i = 0; i < destination.Length; i++) { - destinationSpan[i] = PorterDuffFunctions.Multiply(backgroundSpan[i], sourceSpan[i], amount[i]); + destinationSpan[i] = PorterDuffFunctions.Overlay_Src(backgroundSpan[i], sourceSpan[i], amount[i]); } PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); @@ -102,17 +351,18 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } } - internal class Add : PixelBlender + + internal class HardLight_Src : PixelBlender { /// /// Gets the static instance of this blender. /// - public static Add Instance { get; } = new Add(); + public static HardLight_Src Instance { get; } = new HardLight_Src(); /// public override TPixel Blend(TPixel background, TPixel source, float amount) { - return PorterDuffFunctions.Add(background, source, amount); + return PorterDuffFunctions.HardLight_Src(background, source, amount); } /// @@ -133,7 +383,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders for (int i = 0; i < destination.Length; i++) { - destinationSpan[i] = PorterDuffFunctions.Add(backgroundSpan[i], sourceSpan[i], amount[i]); + destinationSpan[i] = PorterDuffFunctions.HardLight_Src(backgroundSpan[i], sourceSpan[i], amount[i]); } PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); @@ -141,17 +391,18 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } } - internal class Subtract : PixelBlender + + internal class Normal_SrcAtop : PixelBlender { /// /// Gets the static instance of this blender. /// - public static Subtract Instance { get; } = new Subtract(); + public static Normal_SrcAtop Instance { get; } = new Normal_SrcAtop(); /// public override TPixel Blend(TPixel background, TPixel source, float amount) { - return PorterDuffFunctions.Subtract(background, source, amount); + return PorterDuffFunctions.Normal_SrcAtop(background, source, amount); } /// @@ -172,7 +423,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders for (int i = 0; i < destination.Length; i++) { - destinationSpan[i] = PorterDuffFunctions.Subtract(backgroundSpan[i], sourceSpan[i], amount[i]); + destinationSpan[i] = PorterDuffFunctions.Normal_SrcAtop(backgroundSpan[i], sourceSpan[i], amount[i]); } PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); @@ -180,17 +431,18 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } } - internal class Screen : PixelBlender + + internal class Multiply_SrcAtop : PixelBlender { /// /// Gets the static instance of this blender. /// - public static Screen Instance { get; } = new Screen(); + public static Multiply_SrcAtop Instance { get; } = new Multiply_SrcAtop(); /// public override TPixel Blend(TPixel background, TPixel source, float amount) { - return PorterDuffFunctions.Screen(background, source, amount); + return PorterDuffFunctions.Multiply_SrcAtop(background, source, amount); } /// @@ -211,7 +463,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders for (int i = 0; i < destination.Length; i++) { - destinationSpan[i] = PorterDuffFunctions.Screen(backgroundSpan[i], sourceSpan[i], amount[i]); + destinationSpan[i] = PorterDuffFunctions.Multiply_SrcAtop(backgroundSpan[i], sourceSpan[i], amount[i]); } PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); @@ -219,17 +471,18 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } } - internal class Darken : PixelBlender + + internal class Add_SrcAtop : PixelBlender { /// /// Gets the static instance of this blender. /// - public static Darken Instance { get; } = new Darken(); + public static Add_SrcAtop Instance { get; } = new Add_SrcAtop(); /// public override TPixel Blend(TPixel background, TPixel source, float amount) { - return PorterDuffFunctions.Darken(background, source, amount); + return PorterDuffFunctions.Add_SrcAtop(background, source, amount); } /// @@ -250,7 +503,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders for (int i = 0; i < destination.Length; i++) { - destinationSpan[i] = PorterDuffFunctions.Darken(backgroundSpan[i], sourceSpan[i], amount[i]); + destinationSpan[i] = PorterDuffFunctions.Add_SrcAtop(backgroundSpan[i], sourceSpan[i], amount[i]); } PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); @@ -258,17 +511,18 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } } - internal class Lighten : PixelBlender + + internal class Subtract_SrcAtop : PixelBlender { /// /// Gets the static instance of this blender. /// - public static Lighten Instance { get; } = new Lighten(); + public static Subtract_SrcAtop Instance { get; } = new Subtract_SrcAtop(); /// public override TPixel Blend(TPixel background, TPixel source, float amount) { - return PorterDuffFunctions.Lighten(background, source, amount); + return PorterDuffFunctions.Subtract_SrcAtop(background, source, amount); } /// @@ -289,7 +543,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders for (int i = 0; i < destination.Length; i++) { - destinationSpan[i] = PorterDuffFunctions.Lighten(backgroundSpan[i], sourceSpan[i], amount[i]); + destinationSpan[i] = PorterDuffFunctions.Subtract_SrcAtop(backgroundSpan[i], sourceSpan[i], amount[i]); } PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); @@ -297,17 +551,18 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } } - internal class Overlay : PixelBlender + + internal class Screen_SrcAtop : PixelBlender { /// /// Gets the static instance of this blender. /// - public static Overlay Instance { get; } = new Overlay(); + public static Screen_SrcAtop Instance { get; } = new Screen_SrcAtop(); /// public override TPixel Blend(TPixel background, TPixel source, float amount) { - return PorterDuffFunctions.Overlay(background, source, amount); + return PorterDuffFunctions.Screen_SrcAtop(background, source, amount); } /// @@ -328,7 +583,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders for (int i = 0; i < destination.Length; i++) { - destinationSpan[i] = PorterDuffFunctions.Overlay(backgroundSpan[i], sourceSpan[i], amount[i]); + destinationSpan[i] = PorterDuffFunctions.Screen_SrcAtop(backgroundSpan[i], sourceSpan[i], amount[i]); } PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); @@ -336,17 +591,18 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } } - internal class HardLight : PixelBlender + + internal class Darken_SrcAtop : PixelBlender { /// /// Gets the static instance of this blender. /// - public static HardLight Instance { get; } = new HardLight(); + public static Darken_SrcAtop Instance { get; } = new Darken_SrcAtop(); /// public override TPixel Blend(TPixel background, TPixel source, float amount) { - return PorterDuffFunctions.HardLight(background, source, amount); + return PorterDuffFunctions.Darken_SrcAtop(background, source, amount); } /// @@ -367,7 +623,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders for (int i = 0; i < destination.Length; i++) { - destinationSpan[i] = PorterDuffFunctions.HardLight(backgroundSpan[i], sourceSpan[i], amount[i]); + destinationSpan[i] = PorterDuffFunctions.Darken_SrcAtop(backgroundSpan[i], sourceSpan[i], amount[i]); } PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); @@ -375,17 +631,18 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } } - internal class Src : PixelBlender + + internal class Lighten_SrcAtop : PixelBlender { /// /// Gets the static instance of this blender. /// - public static Src Instance { get; } = new Src(); + public static Lighten_SrcAtop Instance { get; } = new Lighten_SrcAtop(); /// public override TPixel Blend(TPixel background, TPixel source, float amount) { - return PorterDuffFunctions.Src(background, source, amount); + return PorterDuffFunctions.Lighten_SrcAtop(background, source, amount); } /// @@ -406,7 +663,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders for (int i = 0; i < destination.Length; i++) { - destinationSpan[i] = PorterDuffFunctions.Src(backgroundSpan[i], sourceSpan[i], amount[i]); + destinationSpan[i] = PorterDuffFunctions.Lighten_SrcAtop(backgroundSpan[i], sourceSpan[i], amount[i]); } PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); @@ -414,17 +671,18 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } } - internal class Atop : PixelBlender + + internal class Overlay_SrcAtop : PixelBlender { /// /// Gets the static instance of this blender. /// - public static Atop Instance { get; } = new Atop(); + public static Overlay_SrcAtop Instance { get; } = new Overlay_SrcAtop(); /// public override TPixel Blend(TPixel background, TPixel source, float amount) { - return PorterDuffFunctions.Atop(background, source, amount); + return PorterDuffFunctions.Overlay_SrcAtop(background, source, amount); } /// @@ -445,7 +703,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders for (int i = 0; i < destination.Length; i++) { - destinationSpan[i] = PorterDuffFunctions.Atop(backgroundSpan[i], sourceSpan[i], amount[i]); + destinationSpan[i] = PorterDuffFunctions.Overlay_SrcAtop(backgroundSpan[i], sourceSpan[i], amount[i]); } PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); @@ -453,17 +711,18 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } } - internal class Over : PixelBlender + + internal class HardLight_SrcAtop : PixelBlender { /// /// Gets the static instance of this blender. /// - public static Over Instance { get; } = new Over(); + public static HardLight_SrcAtop Instance { get; } = new HardLight_SrcAtop(); /// public override TPixel Blend(TPixel background, TPixel source, float amount) { - return PorterDuffFunctions.Over(background, source, amount); + return PorterDuffFunctions.HardLight_SrcAtop(background, source, amount); } /// @@ -484,7 +743,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders for (int i = 0; i < destination.Length; i++) { - destinationSpan[i] = PorterDuffFunctions.Over(backgroundSpan[i], sourceSpan[i], amount[i]); + destinationSpan[i] = PorterDuffFunctions.HardLight_SrcAtop(backgroundSpan[i], sourceSpan[i], amount[i]); } PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); @@ -492,17 +751,18 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } } - internal class In : PixelBlender + + internal class Normal_SrcOver : PixelBlender { /// /// Gets the static instance of this blender. /// - public static In Instance { get; } = new In(); + public static Normal_SrcOver Instance { get; } = new Normal_SrcOver(); /// public override TPixel Blend(TPixel background, TPixel source, float amount) { - return PorterDuffFunctions.In(background, source, amount); + return PorterDuffFunctions.Normal_SrcOver(background, source, amount); } /// @@ -523,7 +783,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders for (int i = 0; i < destination.Length; i++) { - destinationSpan[i] = PorterDuffFunctions.In(backgroundSpan[i], sourceSpan[i], amount[i]); + destinationSpan[i] = PorterDuffFunctions.Normal_SrcOver(backgroundSpan[i], sourceSpan[i], amount[i]); } PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); @@ -531,17 +791,18 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } } - internal class Out : PixelBlender + + internal class Multiply_SrcOver : PixelBlender { /// /// Gets the static instance of this blender. /// - public static Out Instance { get; } = new Out(); + public static Multiply_SrcOver Instance { get; } = new Multiply_SrcOver(); /// public override TPixel Blend(TPixel background, TPixel source, float amount) { - return PorterDuffFunctions.Out(background, source, amount); + return PorterDuffFunctions.Multiply_SrcOver(background, source, amount); } /// @@ -562,7 +823,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders for (int i = 0; i < destination.Length; i++) { - destinationSpan[i] = PorterDuffFunctions.Out(backgroundSpan[i], sourceSpan[i], amount[i]); + destinationSpan[i] = PorterDuffFunctions.Multiply_SrcOver(backgroundSpan[i], sourceSpan[i], amount[i]); } PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); @@ -570,17 +831,18 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } } - internal class Dest : PixelBlender + + internal class Add_SrcOver : PixelBlender { /// /// Gets the static instance of this blender. /// - public static Dest Instance { get; } = new Dest(); + public static Add_SrcOver Instance { get; } = new Add_SrcOver(); /// public override TPixel Blend(TPixel background, TPixel source, float amount) { - return PorterDuffFunctions.Dest(background, source, amount); + return PorterDuffFunctions.Add_SrcOver(background, source, amount); } /// @@ -601,7 +863,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders for (int i = 0; i < destination.Length; i++) { - destinationSpan[i] = PorterDuffFunctions.Dest(backgroundSpan[i], sourceSpan[i], amount[i]); + destinationSpan[i] = PorterDuffFunctions.Add_SrcOver(backgroundSpan[i], sourceSpan[i], amount[i]); } PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); @@ -609,17 +871,18 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } } - internal class DestAtop : PixelBlender + + internal class Subtract_SrcOver : PixelBlender { /// /// Gets the static instance of this blender. /// - public static DestAtop Instance { get; } = new DestAtop(); + public static Subtract_SrcOver Instance { get; } = new Subtract_SrcOver(); /// public override TPixel Blend(TPixel background, TPixel source, float amount) { - return PorterDuffFunctions.DestAtop(background, source, amount); + return PorterDuffFunctions.Subtract_SrcOver(background, source, amount); } /// @@ -640,7 +903,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders for (int i = 0; i < destination.Length; i++) { - destinationSpan[i] = PorterDuffFunctions.DestAtop(backgroundSpan[i], sourceSpan[i], amount[i]); + destinationSpan[i] = PorterDuffFunctions.Subtract_SrcOver(backgroundSpan[i], sourceSpan[i], amount[i]); } PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); @@ -648,17 +911,18 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } } - internal class DestOver : PixelBlender + + internal class Screen_SrcOver : PixelBlender { /// /// Gets the static instance of this blender. /// - public static DestOver Instance { get; } = new DestOver(); + public static Screen_SrcOver Instance { get; } = new Screen_SrcOver(); /// public override TPixel Blend(TPixel background, TPixel source, float amount) { - return PorterDuffFunctions.DestOver(background, source, amount); + return PorterDuffFunctions.Screen_SrcOver(background, source, amount); } /// @@ -679,7 +943,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders for (int i = 0; i < destination.Length; i++) { - destinationSpan[i] = PorterDuffFunctions.DestOver(backgroundSpan[i], sourceSpan[i], amount[i]); + destinationSpan[i] = PorterDuffFunctions.Screen_SrcOver(backgroundSpan[i], sourceSpan[i], amount[i]); } PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); @@ -687,17 +951,18 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } } - internal class DestIn : PixelBlender + + internal class Darken_SrcOver : PixelBlender { /// /// Gets the static instance of this blender. /// - public static DestIn Instance { get; } = new DestIn(); + public static Darken_SrcOver Instance { get; } = new Darken_SrcOver(); /// public override TPixel Blend(TPixel background, TPixel source, float amount) { - return PorterDuffFunctions.DestIn(background, source, amount); + return PorterDuffFunctions.Darken_SrcOver(background, source, amount); } /// @@ -718,7 +983,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders for (int i = 0; i < destination.Length; i++) { - destinationSpan[i] = PorterDuffFunctions.DestIn(backgroundSpan[i], sourceSpan[i], amount[i]); + destinationSpan[i] = PorterDuffFunctions.Darken_SrcOver(backgroundSpan[i], sourceSpan[i], amount[i]); } PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); @@ -726,17 +991,18 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } } - internal class DestOut : PixelBlender + + internal class Lighten_SrcOver : PixelBlender { /// /// Gets the static instance of this blender. /// - public static DestOut Instance { get; } = new DestOut(); + public static Lighten_SrcOver Instance { get; } = new Lighten_SrcOver(); /// public override TPixel Blend(TPixel background, TPixel source, float amount) { - return PorterDuffFunctions.DestOut(background, source, amount); + return PorterDuffFunctions.Lighten_SrcOver(background, source, amount); } /// @@ -757,7 +1023,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders for (int i = 0; i < destination.Length; i++) { - destinationSpan[i] = PorterDuffFunctions.DestOut(backgroundSpan[i], sourceSpan[i], amount[i]); + destinationSpan[i] = PorterDuffFunctions.Lighten_SrcOver(backgroundSpan[i], sourceSpan[i], amount[i]); } PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); @@ -765,17 +1031,18 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } } - internal class Clear : PixelBlender + + internal class Overlay_SrcOver : PixelBlender { /// /// Gets the static instance of this blender. /// - public static Clear Instance { get; } = new Clear(); + public static Overlay_SrcOver Instance { get; } = new Overlay_SrcOver(); /// public override TPixel Blend(TPixel background, TPixel source, float amount) { - return PorterDuffFunctions.Clear(background, source, amount); + return PorterDuffFunctions.Overlay_SrcOver(background, source, amount); } /// @@ -796,7 +1063,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders for (int i = 0; i < destination.Length; i++) { - destinationSpan[i] = PorterDuffFunctions.Clear(backgroundSpan[i], sourceSpan[i], amount[i]); + destinationSpan[i] = PorterDuffFunctions.Overlay_SrcOver(backgroundSpan[i], sourceSpan[i], amount[i]); } PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); @@ -804,17 +1071,18 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } } - internal class Xor : PixelBlender + + internal class HardLight_SrcOver : PixelBlender { /// /// Gets the static instance of this blender. /// - public static Xor Instance { get; } = new Xor(); + public static HardLight_SrcOver Instance { get; } = new HardLight_SrcOver(); /// public override TPixel Blend(TPixel background, TPixel source, float amount) { - return PorterDuffFunctions.Xor(background, source, amount); + return PorterDuffFunctions.HardLight_SrcOver(background, source, amount); } /// @@ -835,7 +1103,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders for (int i = 0; i < destination.Length; i++) { - destinationSpan[i] = PorterDuffFunctions.Xor(backgroundSpan[i], sourceSpan[i], amount[i]); + destinationSpan[i] = PorterDuffFunctions.HardLight_SrcOver(backgroundSpan[i], sourceSpan[i], amount[i]); } PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); @@ -843,5 +1111,3246 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } } + + internal class Normal_SrcIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Normal_SrcIn Instance { get; } = new Normal_SrcIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Normal_SrcIn(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Normal_SrcIn(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Multiply_SrcIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Multiply_SrcIn Instance { get; } = new Multiply_SrcIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Multiply_SrcIn(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Multiply_SrcIn(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Add_SrcIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Add_SrcIn Instance { get; } = new Add_SrcIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Add_SrcIn(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Add_SrcIn(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Subtract_SrcIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Subtract_SrcIn Instance { get; } = new Subtract_SrcIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Subtract_SrcIn(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Subtract_SrcIn(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Screen_SrcIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Screen_SrcIn Instance { get; } = new Screen_SrcIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Screen_SrcIn(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Screen_SrcIn(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Darken_SrcIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Darken_SrcIn Instance { get; } = new Darken_SrcIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Darken_SrcIn(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Darken_SrcIn(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Lighten_SrcIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Lighten_SrcIn Instance { get; } = new Lighten_SrcIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Lighten_SrcIn(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Lighten_SrcIn(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Overlay_SrcIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Overlay_SrcIn Instance { get; } = new Overlay_SrcIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Overlay_SrcIn(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Overlay_SrcIn(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class HardLight_SrcIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static HardLight_SrcIn Instance { get; } = new HardLight_SrcIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.HardLight_SrcIn(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.HardLight_SrcIn(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Normal_SrcOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Normal_SrcOut Instance { get; } = new Normal_SrcOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Normal_SrcOut(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Normal_SrcOut(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Multiply_SrcOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Multiply_SrcOut Instance { get; } = new Multiply_SrcOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Multiply_SrcOut(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Multiply_SrcOut(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Add_SrcOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Add_SrcOut Instance { get; } = new Add_SrcOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Add_SrcOut(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Add_SrcOut(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Subtract_SrcOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Subtract_SrcOut Instance { get; } = new Subtract_SrcOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Subtract_SrcOut(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Subtract_SrcOut(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Screen_SrcOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Screen_SrcOut Instance { get; } = new Screen_SrcOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Screen_SrcOut(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Screen_SrcOut(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Darken_SrcOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Darken_SrcOut Instance { get; } = new Darken_SrcOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Darken_SrcOut(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Darken_SrcOut(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Lighten_SrcOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Lighten_SrcOut Instance { get; } = new Lighten_SrcOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Lighten_SrcOut(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Lighten_SrcOut(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Overlay_SrcOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Overlay_SrcOut Instance { get; } = new Overlay_SrcOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Overlay_SrcOut(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Overlay_SrcOut(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class HardLight_SrcOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static HardLight_SrcOut Instance { get; } = new HardLight_SrcOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.HardLight_SrcOut(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.HardLight_SrcOut(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Normal_Dest : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Normal_Dest Instance { get; } = new Normal_Dest(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Normal_Dest(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Normal_Dest(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Multiply_Dest : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Multiply_Dest Instance { get; } = new Multiply_Dest(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Multiply_Dest(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Multiply_Dest(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Add_Dest : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Add_Dest Instance { get; } = new Add_Dest(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Add_Dest(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Add_Dest(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Subtract_Dest : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Subtract_Dest Instance { get; } = new Subtract_Dest(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Subtract_Dest(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Subtract_Dest(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Screen_Dest : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Screen_Dest Instance { get; } = new Screen_Dest(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Screen_Dest(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Screen_Dest(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Darken_Dest : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Darken_Dest Instance { get; } = new Darken_Dest(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Darken_Dest(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Darken_Dest(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Lighten_Dest : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Lighten_Dest Instance { get; } = new Lighten_Dest(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Lighten_Dest(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Lighten_Dest(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Overlay_Dest : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Overlay_Dest Instance { get; } = new Overlay_Dest(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Overlay_Dest(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Overlay_Dest(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class HardLight_Dest : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static HardLight_Dest Instance { get; } = new HardLight_Dest(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.HardLight_Dest(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.HardLight_Dest(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Normal_DestAtop : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Normal_DestAtop Instance { get; } = new Normal_DestAtop(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Normal_DestAtop(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Normal_DestAtop(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Multiply_DestAtop : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Multiply_DestAtop Instance { get; } = new Multiply_DestAtop(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Multiply_DestAtop(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Multiply_DestAtop(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Add_DestAtop : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Add_DestAtop Instance { get; } = new Add_DestAtop(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Add_DestAtop(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Add_DestAtop(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Subtract_DestAtop : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Subtract_DestAtop Instance { get; } = new Subtract_DestAtop(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Subtract_DestAtop(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Subtract_DestAtop(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Screen_DestAtop : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Screen_DestAtop Instance { get; } = new Screen_DestAtop(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Screen_DestAtop(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Screen_DestAtop(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Darken_DestAtop : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Darken_DestAtop Instance { get; } = new Darken_DestAtop(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Darken_DestAtop(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Darken_DestAtop(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Lighten_DestAtop : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Lighten_DestAtop Instance { get; } = new Lighten_DestAtop(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Lighten_DestAtop(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Lighten_DestAtop(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Overlay_DestAtop : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Overlay_DestAtop Instance { get; } = new Overlay_DestAtop(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Overlay_DestAtop(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Overlay_DestAtop(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class HardLight_DestAtop : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static HardLight_DestAtop Instance { get; } = new HardLight_DestAtop(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.HardLight_DestAtop(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.HardLight_DestAtop(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Normal_DestOver : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Normal_DestOver Instance { get; } = new Normal_DestOver(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Normal_DestOver(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Normal_DestOver(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Multiply_DestOver : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Multiply_DestOver Instance { get; } = new Multiply_DestOver(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Multiply_DestOver(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Multiply_DestOver(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Add_DestOver : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Add_DestOver Instance { get; } = new Add_DestOver(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Add_DestOver(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Add_DestOver(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Subtract_DestOver : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Subtract_DestOver Instance { get; } = new Subtract_DestOver(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Subtract_DestOver(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Subtract_DestOver(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Screen_DestOver : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Screen_DestOver Instance { get; } = new Screen_DestOver(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Screen_DestOver(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Screen_DestOver(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Darken_DestOver : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Darken_DestOver Instance { get; } = new Darken_DestOver(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Darken_DestOver(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Darken_DestOver(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Lighten_DestOver : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Lighten_DestOver Instance { get; } = new Lighten_DestOver(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Lighten_DestOver(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Lighten_DestOver(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Overlay_DestOver : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Overlay_DestOver Instance { get; } = new Overlay_DestOver(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Overlay_DestOver(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Overlay_DestOver(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class HardLight_DestOver : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static HardLight_DestOver Instance { get; } = new HardLight_DestOver(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.HardLight_DestOver(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.HardLight_DestOver(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Normal_DestIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Normal_DestIn Instance { get; } = new Normal_DestIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Normal_DestIn(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Normal_DestIn(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Multiply_DestIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Multiply_DestIn Instance { get; } = new Multiply_DestIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Multiply_DestIn(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Multiply_DestIn(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Add_DestIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Add_DestIn Instance { get; } = new Add_DestIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Add_DestIn(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Add_DestIn(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Subtract_DestIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Subtract_DestIn Instance { get; } = new Subtract_DestIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Subtract_DestIn(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Subtract_DestIn(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Screen_DestIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Screen_DestIn Instance { get; } = new Screen_DestIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Screen_DestIn(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Screen_DestIn(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Darken_DestIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Darken_DestIn Instance { get; } = new Darken_DestIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Darken_DestIn(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Darken_DestIn(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Lighten_DestIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Lighten_DestIn Instance { get; } = new Lighten_DestIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Lighten_DestIn(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Lighten_DestIn(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Overlay_DestIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Overlay_DestIn Instance { get; } = new Overlay_DestIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Overlay_DestIn(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Overlay_DestIn(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class HardLight_DestIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static HardLight_DestIn Instance { get; } = new HardLight_DestIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.HardLight_DestIn(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.HardLight_DestIn(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Normal_DestOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Normal_DestOut Instance { get; } = new Normal_DestOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Normal_DestOut(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Normal_DestOut(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Multiply_DestOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Multiply_DestOut Instance { get; } = new Multiply_DestOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Multiply_DestOut(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Multiply_DestOut(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Add_DestOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Add_DestOut Instance { get; } = new Add_DestOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Add_DestOut(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Add_DestOut(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Subtract_DestOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Subtract_DestOut Instance { get; } = new Subtract_DestOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Subtract_DestOut(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Subtract_DestOut(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Screen_DestOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Screen_DestOut Instance { get; } = new Screen_DestOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Screen_DestOut(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Screen_DestOut(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Darken_DestOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Darken_DestOut Instance { get; } = new Darken_DestOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Darken_DestOut(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Darken_DestOut(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Lighten_DestOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Lighten_DestOut Instance { get; } = new Lighten_DestOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Lighten_DestOut(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Lighten_DestOut(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Overlay_DestOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Overlay_DestOut Instance { get; } = new Overlay_DestOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Overlay_DestOut(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Overlay_DestOut(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class HardLight_DestOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static HardLight_DestOut Instance { get; } = new HardLight_DestOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.HardLight_DestOut(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.HardLight_DestOut(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Normal_Clear : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Normal_Clear Instance { get; } = new Normal_Clear(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Normal_Clear(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Normal_Clear(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Multiply_Clear : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Multiply_Clear Instance { get; } = new Multiply_Clear(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Multiply_Clear(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Multiply_Clear(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Add_Clear : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Add_Clear Instance { get; } = new Add_Clear(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Add_Clear(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Add_Clear(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Subtract_Clear : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Subtract_Clear Instance { get; } = new Subtract_Clear(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Subtract_Clear(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Subtract_Clear(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Screen_Clear : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Screen_Clear Instance { get; } = new Screen_Clear(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Screen_Clear(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Screen_Clear(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Darken_Clear : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Darken_Clear Instance { get; } = new Darken_Clear(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Darken_Clear(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Darken_Clear(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Lighten_Clear : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Lighten_Clear Instance { get; } = new Lighten_Clear(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Lighten_Clear(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Lighten_Clear(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Overlay_Clear : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Overlay_Clear Instance { get; } = new Overlay_Clear(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Overlay_Clear(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Overlay_Clear(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class HardLight_Clear : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static HardLight_Clear Instance { get; } = new HardLight_Clear(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.HardLight_Clear(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.HardLight_Clear(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Normal_Xor : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Normal_Xor Instance { get; } = new Normal_Xor(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Normal_Xor(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Normal_Xor(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Multiply_Xor : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Multiply_Xor Instance { get; } = new Multiply_Xor(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Multiply_Xor(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Multiply_Xor(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Add_Xor : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Add_Xor Instance { get; } = new Add_Xor(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Add_Xor(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Add_Xor(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Subtract_Xor : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Subtract_Xor Instance { get; } = new Subtract_Xor(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Subtract_Xor(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Subtract_Xor(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Screen_Xor : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Screen_Xor Instance { get; } = new Screen_Xor(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Screen_Xor(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Screen_Xor(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Darken_Xor : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Darken_Xor Instance { get; } = new Darken_Xor(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Darken_Xor(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Darken_Xor(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Lighten_Xor : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Lighten_Xor Instance { get; } = new Lighten_Xor(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Lighten_Xor(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Lighten_Xor(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class Overlay_Xor : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static Overlay_Xor Instance { get; } = new Overlay_Xor(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.Overlay_Xor(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.Overlay_Xor(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + + internal class HardLight_Xor : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static HardLight_Xor Instance { get; } = new HardLight_Xor(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + return PorterDuffFunctions.HardLight_Xor(background, source, amount); + } + + /// + public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); + + using (IBuffer buffer = memoryManager.Allocate(destination.Length * 3, false)) + { + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + + PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); + PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); + + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.HardLight_Xor(backgroundSpan[i], sourceSpan[i], amount[i]); + } + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + } + + } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.tt b/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.tt index 07888a756d..c2afc6cf67 100644 --- a/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.tt @@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { using System; using System.Numerics; - using SixLabors.ImageSharp.Memory; + using SixLabors.Memory; /// @@ -35,24 +35,12 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { <# - - - - string[] blenders = new []{ - "Normal", - "Multiply", - "Add", - "Subtract", - "Screen", - "Darken", - "Lighten", - "Overlay", - "HardLight", + string[] composers = new []{ "Src" , - "Atop" , - "Over" , - "In" , - "Out" , + "SrcAtop" , + "SrcOver" , + "SrcIn" , + "SrcOut" , "Dest" , "DestAtop" , "DestOver" , @@ -62,21 +50,37 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders "Xor" , }; + string[] blenders = new []{ + "Normal" , + "Multiply" , + "Add" , + "Subtract" , + "Screen" , + "Darken" , + "Lighten" , + "Overlay" , + "HardLight" + }; + + foreach(var composer in composers) { foreach(var blender in blenders) { + + string blender_composer= $"{blender}_{composer}"; + #> - internal class <#=blender#> : PixelBlender + internal class <#= blender_composer#> : PixelBlender { /// /// Gets the static instance of this blender. /// - public static <#=blender#> Instance { get; } = new <#=blender#>(); + public static <#= blender_composer#> Instance { get; } = new <#= blender_composer#>(); /// public override TPixel Blend(TPixel background, TPixel source, float amount) { - return PorterDuffFunctions.<#=blender#>(background, source, amount); + return PorterDuffFunctions.<#= blender_composer#>(background, source, amount); } /// @@ -97,7 +101,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders for (int i = 0; i < destination.Length; i++) { - destinationSpan[i] = PorterDuffFunctions.<#=blender#>(backgroundSpan[i], sourceSpan[i], amount[i]); + destinationSpan[i] = PorterDuffFunctions.<#= blender_composer#>(backgroundSpan[i], sourceSpan[i], amount[i]); } PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); @@ -106,7 +110,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } <# - + } } #> diff --git a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.cs b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.cs index 66cc427deb..25c22bd502 100644 --- a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.cs @@ -1,4 +1,11 @@ -// Copyright (c) Six Labors and contributors. + + + + + + + +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. // @@ -11,12 +18,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { internal static partial class PorterDuffFunctions { + + + #region Compositors + + [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 Src(Vector4 backdrop, Vector4 source, float opacity) + public static Vector4 Src(Vector4 backdrop, Vector4 source, Vector4 xform) { - opacity = opacity.Clamp(0, 1); - source.W *= opacity; - // calculate weights float xw = backdrop.W * source.W; float bw = backdrop.W - xw; @@ -26,17 +35,15 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders float fw = (sw * 1) + (bw * 0) + (xw * 1); // calculate final value - Vector4 xform = ((source * xw) + (Vector4.Zero * bw) + (source * sw)) / MathF.Max(fw, Constants.Epsilon); + xform = ((xform * xw) + (Vector4.Zero * bw) + (source * sw)) / MathF.Max(fw, Constants.Epsilon); xform.W = fw; - return Vector4.Lerp(backdrop, xform, opacity); + return xform; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 Atop(Vector4 backdrop, Vector4 source, float opacity) + public static Vector4 SrcAtop(Vector4 backdrop, Vector4 source, Vector4 xform) { - opacity = opacity.Clamp(0, 1); - // calculate weights float xw = backdrop.W * source.W; float bw = backdrop.W - xw; @@ -46,18 +53,15 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders float fw = (sw * 0) + (bw * 1) + (xw * 1); // calculate final value - Vector4 xform = ((source * xw) + (backdrop * bw) + (Vector4.Zero * sw)) / MathF.Max(fw, Constants.Epsilon); + xform = ((xform * xw) + (backdrop * bw) + (Vector4.Zero * sw)) / MathF.Max(fw, Constants.Epsilon); xform.W = fw; - return Vector4.Lerp(backdrop, xform, opacity); + return xform; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 Over(Vector4 backdrop, Vector4 source, float opacity) + public static Vector4 SrcOver(Vector4 backdrop, Vector4 source, Vector4 xform) { - opacity = opacity.Clamp(0, 1); - source.W *= opacity; - // calculate weights float xw = backdrop.W * source.W; float bw = backdrop.W - xw; @@ -67,17 +71,15 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders float fw = (sw * 1) + (bw * 1) + (xw * 1); // calculate final value - Vector4 xform = ((source * xw) + (backdrop * bw) + (source * sw)) / MathF.Max(fw, Constants.Epsilon); + xform = ((xform * xw) + (backdrop * bw) + (source * sw)) / MathF.Max(fw, Constants.Epsilon); xform.W = fw; - return Vector4.Lerp(backdrop, xform, opacity); + return xform; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 In(Vector4 backdrop, Vector4 source, float opacity) + public static Vector4 SrcIn(Vector4 backdrop, Vector4 source, Vector4 xform) { - opacity = opacity.Clamp(0, 1); - // calculate weights float xw = backdrop.W * source.W; float bw = backdrop.W - xw; @@ -87,18 +89,15 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders float fw = (sw * 0) + (bw * 0) + (xw * 1); // calculate final value - Vector4 xform = ((source * xw) + (Vector4.Zero * bw) + (Vector4.Zero * sw)) / MathF.Max(fw, Constants.Epsilon); + xform = ((xform * xw) + (Vector4.Zero * bw) + (Vector4.Zero * sw)) / MathF.Max(fw, Constants.Epsilon); xform.W = fw; - return Vector4.Lerp(backdrop, xform, opacity); + return xform; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 Out(Vector4 backdrop, Vector4 source, float opacity) + public static Vector4 SrcOut(Vector4 backdrop, Vector4 source, Vector4 xform) { - opacity = opacity.Clamp(0, 1); - source.W *= opacity; - // calculate weights float xw = backdrop.W * source.W; float bw = backdrop.W - xw; @@ -108,17 +107,15 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders float fw = (sw * 1) + (bw * 0) + (xw * 0); // calculate final value - Vector4 xform = ((Vector4.Zero * xw) + (Vector4.Zero * bw) + (source * sw)) / MathF.Max(fw, Constants.Epsilon); + xform = ((Vector4.Zero * xw) + (Vector4.Zero * bw) + (source * sw)) / MathF.Max(fw, Constants.Epsilon); xform.W = fw; - return Vector4.Lerp(backdrop, xform, opacity); + return xform; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 Dest(Vector4 backdrop, Vector4 source, float opacity) + public static Vector4 Dest(Vector4 backdrop, Vector4 source, Vector4 xform) { - opacity = opacity.Clamp(0, 1); - // calculate weights float xw = backdrop.W * source.W; float bw = backdrop.W - xw; @@ -128,18 +125,15 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders float fw = (sw * 0) + (bw * 1) + (xw * 1); // calculate final value - Vector4 xform = ((backdrop * xw) + (backdrop * bw) + (Vector4.Zero * sw)) / MathF.Max(fw, Constants.Epsilon); + xform = ((backdrop * xw) + (backdrop * bw) + (Vector4.Zero * sw)) / MathF.Max(fw, Constants.Epsilon); xform.W = fw; - return Vector4.Lerp(backdrop, xform, opacity); + return xform; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 DestAtop(Vector4 backdrop, Vector4 source, float opacity) + public static Vector4 DestAtop(Vector4 backdrop, Vector4 source, Vector4 xform) { - opacity = opacity.Clamp(0, 1); - source.W *= opacity; - // calculate weights float xw = backdrop.W * source.W; float bw = backdrop.W - xw; @@ -149,18 +143,15 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders float fw = (sw * 1) + (bw * 0) + (xw * 1); // calculate final value - Vector4 xform = ((backdrop * xw) + (Vector4.Zero * bw) + (source * sw)) / MathF.Max(fw, Constants.Epsilon); + xform = ((backdrop * xw) + (Vector4.Zero * bw) + (source * sw)) / MathF.Max(fw, Constants.Epsilon); xform.W = fw; - return Vector4.Lerp(backdrop, xform, opacity); + return xform; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 DestOver(Vector4 backdrop, Vector4 source, float opacity) + public static Vector4 DestOver(Vector4 backdrop, Vector4 source, Vector4 xform) { - opacity = opacity.Clamp(0, 1); - source.W *= opacity; - // calculate weights float xw = backdrop.W * source.W; float bw = backdrop.W - xw; @@ -170,17 +161,15 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders float fw = (sw * 1) + (bw * 1) + (xw * 1); // calculate final value - Vector4 xform = ((backdrop * xw) + (backdrop * bw) + (source * sw)) / MathF.Max(fw, Constants.Epsilon); + xform = ((backdrop * xw) + (backdrop * bw) + (source * sw)) / MathF.Max(fw, Constants.Epsilon); xform.W = fw; - return Vector4.Lerp(backdrop, xform, opacity); + return xform; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 DestIn(Vector4 backdrop, Vector4 source, float opacity) + public static Vector4 DestIn(Vector4 backdrop, Vector4 source, Vector4 xform) { - opacity = opacity.Clamp(0, 1); - // calculate weights float xw = backdrop.W * source.W; float bw = backdrop.W - xw; @@ -190,17 +179,15 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders float fw = (sw * 0) + (bw * 0) + (xw * 1); // calculate final value - Vector4 xform = ((backdrop * xw) + (Vector4.Zero * bw) + (Vector4.Zero * sw)) / MathF.Max(fw, Constants.Epsilon); + xform = ((backdrop * xw) + (Vector4.Zero * bw) + (Vector4.Zero * sw)) / MathF.Max(fw, Constants.Epsilon); xform.W = fw; - return Vector4.Lerp(backdrop, xform, opacity); + return xform; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 DestOut(Vector4 backdrop, Vector4 source, float opacity) + public static Vector4 DestOut(Vector4 backdrop, Vector4 source, Vector4 xform) { - opacity = opacity.Clamp(0, 1); - // calculate weights float xw = backdrop.W * source.W; float bw = backdrop.W - xw; @@ -210,17 +197,15 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders float fw = (sw * 0) + (bw * 1) + (xw * 0); // calculate final value - Vector4 xform = ((Vector4.Zero * xw) + (backdrop * bw) + (Vector4.Zero * sw)) / MathF.Max(fw, Constants.Epsilon); + xform = ((Vector4.Zero * xw) + (backdrop * bw) + (Vector4.Zero * sw)) / MathF.Max(fw, Constants.Epsilon); xform.W = fw; - return Vector4.Lerp(backdrop, xform, opacity); + return xform; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 Clear(Vector4 backdrop, Vector4 source, float opacity) + public static Vector4 Clear(Vector4 backdrop, Vector4 source, Vector4 xform) { - opacity = opacity.Clamp(0, 1); - // calculate weights float xw = backdrop.W * source.W; float bw = backdrop.W - xw; @@ -230,18 +215,15 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders float fw = (sw * 0) + (bw * 0) + (xw * 0); // calculate final value - Vector4 xform = ((Vector4.Zero * xw) + (Vector4.Zero * bw) + (Vector4.Zero * sw)) / MathF.Max(fw, Constants.Epsilon); + xform = ((Vector4.Zero * xw) + (Vector4.Zero * bw) + (Vector4.Zero * sw)) / MathF.Max(fw, Constants.Epsilon); xform.W = fw; - return Vector4.Lerp(backdrop, xform, opacity); + return xform; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 Xor(Vector4 backdrop, Vector4 source, float opacity) + public static Vector4 Xor(Vector4 backdrop, Vector4 source, Vector4 xform) { - opacity = opacity.Clamp(0, 1); - source.W *= opacity; - // calculate weights float xw = backdrop.W * source.W; float bw = backdrop.W - xw; @@ -251,200 +233,2827 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders float fw = (sw * 1) + (bw * 1) + (xw * 0); // calculate final value - Vector4 xform = ((Vector4.Zero * xw) + (backdrop * bw) + (source * sw)) / MathF.Max(fw, Constants.Epsilon); + xform = ((Vector4.Zero * xw) + (backdrop * bw) + (source * sw)) / MathF.Max(fw, Constants.Epsilon); xform.W = fw; - return Vector4.Lerp(backdrop, xform, opacity); + return xform; + } + + + #endregion + + #region Blenders + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Normal_Src(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Src(backdrop,source, Normal(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Normal_Src(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(Src(backdropV,sourceV, Normal(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Multiply_Src(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Src(backdrop,source, Multiply(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Multiply_Src(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(Src(backdropV,sourceV, Multiply(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Add_Src(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Src(backdrop,source, Add(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Add_Src(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(Src(backdropV,sourceV, Add(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Subtract_Src(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Src(backdrop,source, Subtract(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Subtract_Src(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(Src(backdropV,sourceV, Subtract(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Screen_Src(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Src(backdrop,source, Screen(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Screen_Src(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(Src(backdropV,sourceV, Screen(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Darken_Src(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Src(backdrop,source, Darken(backdrop, source)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel Normal(TPixel backdrop, TPixel source, float amount) + public static TPixel Darken_Src(TPixel backdrop, TPixel source, float opacity) where TPixel : struct, IPixel { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + TPixel dest = default; - dest.PackFromVector4(Normal(backdrop.ToVector4(), source.ToVector4(), amount)); + dest.PackFromVector4(Src(backdropV,sourceV, Darken(backdropV, sourceV))); return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Lighten_Src(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Src(backdrop,source, Lighten(backdrop, source)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel Multiply(TPixel backdrop, TPixel source, float amount) + public static TPixel Lighten_Src(TPixel backdrop, TPixel source, float opacity) where TPixel : struct, IPixel { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + TPixel dest = default; - dest.PackFromVector4(Multiply(backdrop.ToVector4(), source.ToVector4(), amount)); + dest.PackFromVector4(Src(backdropV,sourceV, Lighten(backdropV, sourceV))); return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Overlay_Src(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Src(backdrop,source, Overlay(backdrop, source)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel Add(TPixel backdrop, TPixel source, float amount) + public static TPixel Overlay_Src(TPixel backdrop, TPixel source, float opacity) where TPixel : struct, IPixel { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + TPixel dest = default; - dest.PackFromVector4(Add(backdrop.ToVector4(), source.ToVector4(), amount)); + dest.PackFromVector4(Src(backdropV,sourceV, Overlay(backdropV, sourceV))); return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 HardLight_Src(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Src(backdrop,source, HardLight(backdrop, source)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel Subtract(TPixel backdrop, TPixel source, float amount) + public static TPixel HardLight_Src(TPixel backdrop, TPixel source, float opacity) where TPixel : struct, IPixel { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + TPixel dest = default; - dest.PackFromVector4(Subtract(backdrop.ToVector4(), source.ToVector4(), amount)); + dest.PackFromVector4(Src(backdropV,sourceV, HardLight(backdropV, sourceV))); return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Normal_SrcAtop(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcAtop(backdrop,source, Normal(backdrop, source)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel Screen(TPixel backdrop, TPixel source, float amount) + public static TPixel Normal_SrcAtop(TPixel backdrop, TPixel source, float opacity) where TPixel : struct, IPixel { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + TPixel dest = default; - dest.PackFromVector4(Screen(backdrop.ToVector4(), source.ToVector4(), amount)); + dest.PackFromVector4(SrcAtop(backdropV,sourceV, Normal(backdropV, sourceV))); return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Multiply_SrcAtop(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcAtop(backdrop,source, Multiply(backdrop, source)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel Darken(TPixel backdrop, TPixel source, float amount) + public static TPixel Multiply_SrcAtop(TPixel backdrop, TPixel source, float opacity) where TPixel : struct, IPixel { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + TPixel dest = default; - dest.PackFromVector4(Darken(backdrop.ToVector4(), source.ToVector4(), amount)); + dest.PackFromVector4(SrcAtop(backdropV,sourceV, Multiply(backdropV, sourceV))); return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Add_SrcAtop(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcAtop(backdrop,source, Add(backdrop, source)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel Lighten(TPixel backdrop, TPixel source, float amount) + public static TPixel Add_SrcAtop(TPixel backdrop, TPixel source, float opacity) where TPixel : struct, IPixel { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + TPixel dest = default; - dest.PackFromVector4(Lighten(backdrop.ToVector4(), source.ToVector4(), amount)); + dest.PackFromVector4(SrcAtop(backdropV,sourceV, Add(backdropV, sourceV))); return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Subtract_SrcAtop(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcAtop(backdrop,source, Subtract(backdrop, source)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel Overlay(TPixel backdrop, TPixel source, float amount) + public static TPixel Subtract_SrcAtop(TPixel backdrop, TPixel source, float opacity) where TPixel : struct, IPixel { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + TPixel dest = default; - dest.PackFromVector4(Overlay(backdrop.ToVector4(), source.ToVector4(), amount)); + dest.PackFromVector4(SrcAtop(backdropV,sourceV, Subtract(backdropV, sourceV))); return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Screen_SrcAtop(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcAtop(backdrop,source, Screen(backdrop, source)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel HardLight(TPixel backdrop, TPixel source, float amount) + public static TPixel Screen_SrcAtop(TPixel backdrop, TPixel source, float opacity) where TPixel : struct, IPixel { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + TPixel dest = default; - dest.PackFromVector4(HardLight(backdrop.ToVector4(), source.ToVector4(), amount)); + dest.PackFromVector4(SrcAtop(backdropV,sourceV, Screen(backdropV, sourceV))); return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Darken_SrcAtop(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcAtop(backdrop,source, Darken(backdrop, source)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel Src(TPixel backdrop, TPixel source, float amount) + public static TPixel Darken_SrcAtop(TPixel backdrop, TPixel source, float opacity) where TPixel : struct, IPixel { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + TPixel dest = default; - dest.PackFromVector4(Src(backdrop.ToVector4(), source.ToVector4(), amount)); + dest.PackFromVector4(SrcAtop(backdropV,sourceV, Darken(backdropV, sourceV))); return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Lighten_SrcAtop(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcAtop(backdrop,source, Lighten(backdrop, source)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel Atop(TPixel backdrop, TPixel source, float amount) + public static TPixel Lighten_SrcAtop(TPixel backdrop, TPixel source, float opacity) where TPixel : struct, IPixel { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + TPixel dest = default; - dest.PackFromVector4(Atop(backdrop.ToVector4(), source.ToVector4(), amount)); + dest.PackFromVector4(SrcAtop(backdropV,sourceV, Lighten(backdropV, sourceV))); return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Overlay_SrcAtop(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcAtop(backdrop,source, Overlay(backdrop, source)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel Over(TPixel backdrop, TPixel source, float amount) + public static TPixel Overlay_SrcAtop(TPixel backdrop, TPixel source, float opacity) where TPixel : struct, IPixel { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + TPixel dest = default; - dest.PackFromVector4(Over(backdrop.ToVector4(), source.ToVector4(), amount)); + dest.PackFromVector4(SrcAtop(backdropV,sourceV, Overlay(backdropV, sourceV))); return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 HardLight_SrcAtop(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcAtop(backdrop,source, HardLight(backdrop, source)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel In(TPixel backdrop, TPixel source, float amount) + public static TPixel HardLight_SrcAtop(TPixel backdrop, TPixel source, float opacity) where TPixel : struct, IPixel { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + TPixel dest = default; - dest.PackFromVector4(In(backdrop.ToVector4(), source.ToVector4(), amount)); + dest.PackFromVector4(SrcAtop(backdropV,sourceV, HardLight(backdropV, sourceV))); return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Normal_SrcOver(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcOver(backdrop,source, Normal(backdrop, source)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel Out(TPixel backdrop, TPixel source, float amount) + public static TPixel Normal_SrcOver(TPixel backdrop, TPixel source, float opacity) where TPixel : struct, IPixel { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + TPixel dest = default; - dest.PackFromVector4(Out(backdrop.ToVector4(), source.ToVector4(), amount)); + dest.PackFromVector4(SrcOver(backdropV,sourceV, Normal(backdropV, sourceV))); return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Multiply_SrcOver(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcOver(backdrop,source, Multiply(backdrop, source)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel Dest(TPixel backdrop, TPixel source, float amount) + public static TPixel Multiply_SrcOver(TPixel backdrop, TPixel source, float opacity) where TPixel : struct, IPixel { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + TPixel dest = default; - dest.PackFromVector4(Dest(backdrop.ToVector4(), source.ToVector4(), amount)); + dest.PackFromVector4(SrcOver(backdropV,sourceV, Multiply(backdropV, sourceV))); return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Add_SrcOver(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcOver(backdrop,source, Add(backdrop, source)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel DestAtop(TPixel backdrop, TPixel source, float amount) + public static TPixel Add_SrcOver(TPixel backdrop, TPixel source, float opacity) where TPixel : struct, IPixel { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + TPixel dest = default; - dest.PackFromVector4(DestAtop(backdrop.ToVector4(), source.ToVector4(), amount)); + dest.PackFromVector4(SrcOver(backdropV,sourceV, Add(backdropV, sourceV))); return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Subtract_SrcOver(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcOver(backdrop,source, Subtract(backdrop, source)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel DestOver(TPixel backdrop, TPixel source, float amount) + public static TPixel Subtract_SrcOver(TPixel backdrop, TPixel source, float opacity) where TPixel : struct, IPixel { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + TPixel dest = default; - dest.PackFromVector4(DestOver(backdrop.ToVector4(), source.ToVector4(), amount)); + dest.PackFromVector4(SrcOver(backdropV,sourceV, Subtract(backdropV, sourceV))); return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Screen_SrcOver(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcOver(backdrop,source, Screen(backdrop, source)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel DestIn(TPixel backdrop, TPixel source, float amount) + public static TPixel Screen_SrcOver(TPixel backdrop, TPixel source, float opacity) where TPixel : struct, IPixel { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + TPixel dest = default; - dest.PackFromVector4(DestIn(backdrop.ToVector4(), source.ToVector4(), amount)); + dest.PackFromVector4(SrcOver(backdropV,sourceV, Screen(backdropV, sourceV))); return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Darken_SrcOver(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcOver(backdrop,source, Darken(backdrop, source)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel DestOut(TPixel backdrop, TPixel source, float amount) + public static TPixel Darken_SrcOver(TPixel backdrop, TPixel source, float opacity) where TPixel : struct, IPixel { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + TPixel dest = default; - dest.PackFromVector4(DestOut(backdrop.ToVector4(), source.ToVector4(), amount)); + dest.PackFromVector4(SrcOver(backdropV,sourceV, Darken(backdropV, sourceV))); return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Lighten_SrcOver(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcOver(backdrop,source, Lighten(backdrop, source)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel Clear(TPixel backdrop, TPixel source, float amount) + public static TPixel Lighten_SrcOver(TPixel backdrop, TPixel source, float opacity) where TPixel : struct, IPixel { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + TPixel dest = default; - dest.PackFromVector4(Clear(backdrop.ToVector4(), source.ToVector4(), amount)); + dest.PackFromVector4(SrcOver(backdropV,sourceV, Lighten(backdropV, sourceV))); return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Overlay_SrcOver(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcOver(backdrop,source, Overlay(backdrop, source)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel Xor(TPixel backdrop, TPixel source, float amount) + public static TPixel Overlay_SrcOver(TPixel backdrop, TPixel source, float opacity) where TPixel : struct, IPixel { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + TPixel dest = default; - dest.PackFromVector4(Xor(backdrop.ToVector4(), source.ToVector4(), amount)); + dest.PackFromVector4(SrcOver(backdropV,sourceV, Overlay(backdropV, sourceV))); return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 HardLight_SrcOver(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcOver(backdrop,source, HardLight(backdrop, source)); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel HardLight_SrcOver(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(SrcOver(backdropV,sourceV, HardLight(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Normal_SrcIn(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcIn(backdrop,source, Normal(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Normal_SrcIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(SrcIn(backdropV,sourceV, Normal(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Multiply_SrcIn(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcIn(backdrop,source, Multiply(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Multiply_SrcIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(SrcIn(backdropV,sourceV, Multiply(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Add_SrcIn(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcIn(backdrop,source, Add(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Add_SrcIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(SrcIn(backdropV,sourceV, Add(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Subtract_SrcIn(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcIn(backdrop,source, Subtract(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Subtract_SrcIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(SrcIn(backdropV,sourceV, Subtract(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Screen_SrcIn(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcIn(backdrop,source, Screen(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Screen_SrcIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(SrcIn(backdropV,sourceV, Screen(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Darken_SrcIn(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcIn(backdrop,source, Darken(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Darken_SrcIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(SrcIn(backdropV,sourceV, Darken(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Lighten_SrcIn(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcIn(backdrop,source, Lighten(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Lighten_SrcIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(SrcIn(backdropV,sourceV, Lighten(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Overlay_SrcIn(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcIn(backdrop,source, Overlay(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Overlay_SrcIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(SrcIn(backdropV,sourceV, Overlay(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 HardLight_SrcIn(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcIn(backdrop,source, HardLight(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel HardLight_SrcIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(SrcIn(backdropV,sourceV, HardLight(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Normal_SrcOut(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcOut(backdrop,source, Normal(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Normal_SrcOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(SrcOut(backdropV,sourceV, Normal(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Multiply_SrcOut(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcOut(backdrop,source, Multiply(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Multiply_SrcOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(SrcOut(backdropV,sourceV, Multiply(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Add_SrcOut(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcOut(backdrop,source, Add(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Add_SrcOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(SrcOut(backdropV,sourceV, Add(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Subtract_SrcOut(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcOut(backdrop,source, Subtract(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Subtract_SrcOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(SrcOut(backdropV,sourceV, Subtract(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Screen_SrcOut(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcOut(backdrop,source, Screen(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Screen_SrcOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(SrcOut(backdropV,sourceV, Screen(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Darken_SrcOut(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcOut(backdrop,source, Darken(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Darken_SrcOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(SrcOut(backdropV,sourceV, Darken(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Lighten_SrcOut(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcOut(backdrop,source, Lighten(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Lighten_SrcOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(SrcOut(backdropV,sourceV, Lighten(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Overlay_SrcOut(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcOut(backdrop,source, Overlay(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Overlay_SrcOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(SrcOut(backdropV,sourceV, Overlay(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 HardLight_SrcOut(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return SrcOut(backdrop,source, HardLight(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel HardLight_SrcOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(SrcOut(backdropV,sourceV, HardLight(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Normal_Dest(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Dest(backdrop,source, Normal(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Normal_Dest(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(Dest(backdropV,sourceV, Normal(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Multiply_Dest(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Dest(backdrop,source, Multiply(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Multiply_Dest(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(Dest(backdropV,sourceV, Multiply(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Add_Dest(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Dest(backdrop,source, Add(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Add_Dest(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(Dest(backdropV,sourceV, Add(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Subtract_Dest(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Dest(backdrop,source, Subtract(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Subtract_Dest(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(Dest(backdropV,sourceV, Subtract(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Screen_Dest(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Dest(backdrop,source, Screen(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Screen_Dest(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(Dest(backdropV,sourceV, Screen(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Darken_Dest(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Dest(backdrop,source, Darken(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Darken_Dest(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(Dest(backdropV,sourceV, Darken(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Lighten_Dest(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Dest(backdrop,source, Lighten(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Lighten_Dest(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(Dest(backdropV,sourceV, Lighten(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Overlay_Dest(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Dest(backdrop,source, Overlay(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Overlay_Dest(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(Dest(backdropV,sourceV, Overlay(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 HardLight_Dest(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Dest(backdrop,source, HardLight(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel HardLight_Dest(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(Dest(backdropV,sourceV, HardLight(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Normal_DestAtop(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestAtop(backdrop,source, Normal(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Normal_DestAtop(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestAtop(backdropV,sourceV, Normal(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Multiply_DestAtop(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestAtop(backdrop,source, Multiply(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Multiply_DestAtop(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestAtop(backdropV,sourceV, Multiply(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Add_DestAtop(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestAtop(backdrop,source, Add(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Add_DestAtop(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestAtop(backdropV,sourceV, Add(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Subtract_DestAtop(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestAtop(backdrop,source, Subtract(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Subtract_DestAtop(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestAtop(backdropV,sourceV, Subtract(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Screen_DestAtop(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestAtop(backdrop,source, Screen(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Screen_DestAtop(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestAtop(backdropV,sourceV, Screen(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Darken_DestAtop(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestAtop(backdrop,source, Darken(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Darken_DestAtop(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestAtop(backdropV,sourceV, Darken(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Lighten_DestAtop(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestAtop(backdrop,source, Lighten(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Lighten_DestAtop(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestAtop(backdropV,sourceV, Lighten(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Overlay_DestAtop(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestAtop(backdrop,source, Overlay(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Overlay_DestAtop(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestAtop(backdropV,sourceV, Overlay(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 HardLight_DestAtop(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestAtop(backdrop,source, HardLight(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel HardLight_DestAtop(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestAtop(backdropV,sourceV, HardLight(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Normal_DestOver(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestOver(backdrop,source, Normal(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Normal_DestOver(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestOver(backdropV,sourceV, Normal(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Multiply_DestOver(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestOver(backdrop,source, Multiply(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Multiply_DestOver(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestOver(backdropV,sourceV, Multiply(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Add_DestOver(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestOver(backdrop,source, Add(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Add_DestOver(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestOver(backdropV,sourceV, Add(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Subtract_DestOver(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestOver(backdrop,source, Subtract(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Subtract_DestOver(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestOver(backdropV,sourceV, Subtract(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Screen_DestOver(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestOver(backdrop,source, Screen(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Screen_DestOver(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestOver(backdropV,sourceV, Screen(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Darken_DestOver(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestOver(backdrop,source, Darken(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Darken_DestOver(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestOver(backdropV,sourceV, Darken(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Lighten_DestOver(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestOver(backdrop,source, Lighten(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Lighten_DestOver(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestOver(backdropV,sourceV, Lighten(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Overlay_DestOver(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestOver(backdrop,source, Overlay(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Overlay_DestOver(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestOver(backdropV,sourceV, Overlay(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 HardLight_DestOver(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestOver(backdrop,source, HardLight(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel HardLight_DestOver(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestOver(backdropV,sourceV, HardLight(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Normal_DestIn(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestIn(backdrop,source, Normal(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Normal_DestIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestIn(backdropV,sourceV, Normal(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Multiply_DestIn(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestIn(backdrop,source, Multiply(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Multiply_DestIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestIn(backdropV,sourceV, Multiply(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Add_DestIn(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestIn(backdrop,source, Add(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Add_DestIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestIn(backdropV,sourceV, Add(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Subtract_DestIn(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestIn(backdrop,source, Subtract(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Subtract_DestIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestIn(backdropV,sourceV, Subtract(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Screen_DestIn(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestIn(backdrop,source, Screen(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Screen_DestIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestIn(backdropV,sourceV, Screen(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Darken_DestIn(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestIn(backdrop,source, Darken(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Darken_DestIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestIn(backdropV,sourceV, Darken(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Lighten_DestIn(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestIn(backdrop,source, Lighten(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Lighten_DestIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestIn(backdropV,sourceV, Lighten(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Overlay_DestIn(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestIn(backdrop,source, Overlay(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Overlay_DestIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestIn(backdropV,sourceV, Overlay(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 HardLight_DestIn(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestIn(backdrop,source, HardLight(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel HardLight_DestIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestIn(backdropV,sourceV, HardLight(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Normal_DestOut(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestOut(backdrop,source, Normal(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Normal_DestOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestOut(backdropV,sourceV, Normal(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Multiply_DestOut(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestOut(backdrop,source, Multiply(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Multiply_DestOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestOut(backdropV,sourceV, Multiply(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Add_DestOut(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestOut(backdrop,source, Add(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Add_DestOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestOut(backdropV,sourceV, Add(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Subtract_DestOut(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestOut(backdrop,source, Subtract(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Subtract_DestOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestOut(backdropV,sourceV, Subtract(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Screen_DestOut(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestOut(backdrop,source, Screen(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Screen_DestOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestOut(backdropV,sourceV, Screen(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Darken_DestOut(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestOut(backdrop,source, Darken(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Darken_DestOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestOut(backdropV,sourceV, Darken(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Lighten_DestOut(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestOut(backdrop,source, Lighten(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Lighten_DestOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestOut(backdropV,sourceV, Lighten(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Overlay_DestOut(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestOut(backdrop,source, Overlay(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Overlay_DestOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestOut(backdropV,sourceV, Overlay(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 HardLight_DestOut(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return DestOut(backdrop,source, HardLight(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel HardLight_DestOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(DestOut(backdropV,sourceV, HardLight(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Normal_Clear(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Clear(backdrop,source, Normal(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Normal_Clear(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(Clear(backdropV,sourceV, Normal(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Multiply_Clear(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Clear(backdrop,source, Multiply(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Multiply_Clear(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(Clear(backdropV,sourceV, Multiply(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Add_Clear(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Clear(backdrop,source, Add(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Add_Clear(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(Clear(backdropV,sourceV, Add(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Subtract_Clear(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Clear(backdrop,source, Subtract(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Subtract_Clear(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(Clear(backdropV,sourceV, Subtract(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Screen_Clear(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Clear(backdrop,source, Screen(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Screen_Clear(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(Clear(backdropV,sourceV, Screen(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Darken_Clear(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Clear(backdrop,source, Darken(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Darken_Clear(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(Clear(backdropV,sourceV, Darken(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Lighten_Clear(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Clear(backdrop,source, Lighten(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Lighten_Clear(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(Clear(backdropV,sourceV, Lighten(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Overlay_Clear(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Clear(backdrop,source, Overlay(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Overlay_Clear(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(Clear(backdropV,sourceV, Overlay(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 HardLight_Clear(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Clear(backdrop,source, HardLight(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel HardLight_Clear(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(Clear(backdropV,sourceV, HardLight(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Normal_Xor(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Xor(backdrop,source, Normal(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Normal_Xor(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(Xor(backdropV,sourceV, Normal(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Multiply_Xor(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Xor(backdrop,source, Multiply(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Multiply_Xor(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(Xor(backdropV,sourceV, Multiply(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Add_Xor(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Xor(backdrop,source, Add(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Add_Xor(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(Xor(backdropV,sourceV, Add(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Subtract_Xor(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Xor(backdrop,source, Subtract(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Subtract_Xor(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(Xor(backdropV,sourceV, Subtract(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Screen_Xor(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Xor(backdrop,source, Screen(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Screen_Xor(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(Xor(backdropV,sourceV, Screen(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Darken_Xor(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Xor(backdrop,source, Darken(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Darken_Xor(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(Xor(backdropV,sourceV, Darken(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Lighten_Xor(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Xor(backdrop,source, Lighten(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Lighten_Xor(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(Xor(backdropV,sourceV, Lighten(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Overlay_Xor(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Xor(backdrop,source, Overlay(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel Overlay_Xor(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(Xor(backdropV,sourceV, Overlay(backdropV, sourceV))); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 HardLight_Xor(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return Xor(backdrop,source, HardLight(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel HardLight_Xor(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(Xor(backdropV,sourceV, HardLight(backdropV, sourceV))); + return dest; + } + + + + #endregion } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.tt b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.tt index 4cbc068618..25f1e76487 100644 --- a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.tt @@ -21,37 +21,15 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { internal static partial class PorterDuffFunctions { -<# - - void GeneratePixelBlender (string blender) - { -#> - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel <#=blender#>(TPixel backdrop, TPixel source, float amount) - where TPixel : struct, IPixel - { - TPixel dest = default; - dest.PackFromVector4(<#=blender#>(backdrop.ToVector4(), source.ToVector4(), amount)); - return dest; - } - -<# - } - - void GenerateVectorCompositor(string name, string sourceVar, string destVar, string blendVar) +<# void GenerateVectorCompositor(string name, string sourceVar, string destVar, string blendVar) { int a_s = sourceVar == "Vector4.Zero" ? 0 : 1; int a_b = destVar == "Vector4.Zero" ? 0 : 1; int a_x = blendVar == "Vector4.Zero" ? 0 : 1; #> [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 <#=name#>(Vector4 backdrop, Vector4 source, float opacity) + public static Vector4 <#=name#>(Vector4 backdrop, Vector4 source, Vector4 xform) { - opacity = opacity.Clamp(0, 1); -<# if(sourceVar != "Vector4.Zero" ) { #> - source.W *= opacity; -<# } #> - // calculate weights float xw = backdrop.W * source.W; float bw = backdrop.W - xw; @@ -61,52 +39,98 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders float fw = (sw * <#=a_s#>) + (bw * <#=a_b#>) + (xw * <#=a_x#>); // calculate final value - Vector4 xform = ((<#=blendVar#> * xw) + (<#=destVar#> * bw) + (<#=sourceVar#> * sw)) / MathF.Max(fw, Constants.Epsilon); + xform = ((<#=blendVar#> * xw) + (<#=destVar#> * bw) + (<#=sourceVar#> * sw)) / MathF.Max(fw, Constants.Epsilon); xform.W = fw; - return Vector4.Lerp(backdrop, xform, opacity); + return xform; + } +<# } #> +<# void GeneratePixelBlender(string blender, string compositor) { #> + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 <#=blender#>_<#=compositor#>(Vector4 backdrop, Vector4 source, float opacity) + { + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + + return <#=compositor#>(backdrop,source, <#=blender#>(backdrop, source)); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel <#=blender#>_<#=compositor#>(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + + Vector4 backdropV = backdrop.ToVector4(); + Vector4 sourceV = source.ToVector4(); + sourceV.W *= opacity; + + TPixel dest = default; + dest.PackFromVector4(<#=compositor#>(backdropV,sourceV, <#=blender#>(backdropV, sourceV))); + return dest; + } + +<# } #> + #region Compositors + <# - } - GenerateVectorCompositor("Src", "source", "Vector4.Zero", "source"); - GenerateVectorCompositor("Atop", "Vector4.Zero", "backdrop", "source"); - GenerateVectorCompositor("Over", "source", "backdrop", "source"); - GenerateVectorCompositor("In", "Vector4.Zero", "Vector4.Zero", "source"); - GenerateVectorCompositor("Out", "source", "Vector4.Zero", "Vector4.Zero"); - GenerateVectorCompositor("Dest", "Vector4.Zero", "backdrop", "backdrop"); - GenerateVectorCompositor("DestAtop", "source", "Vector4.Zero", "backdrop"); - GenerateVectorCompositor("DestOver", "source", "backdrop", "backdrop"); - GenerateVectorCompositor("DestIn", "Vector4.Zero", "Vector4.Zero", "backdrop"); - GenerateVectorCompositor("DestOut", "Vector4.Zero", "backdrop", "Vector4.Zero"); - GenerateVectorCompositor("Clear", "Vector4.Zero", "Vector4.Zero", "Vector4.Zero"); - GenerateVectorCompositor("Xor", "source", "backdrop", "Vector4.Zero"); - - - GeneratePixelBlender("Normal"); - GeneratePixelBlender("Multiply"); - GeneratePixelBlender("Add"); - GeneratePixelBlender("Subtract"); - GeneratePixelBlender("Screen"); - GeneratePixelBlender("Darken"); - GeneratePixelBlender("Lighten"); - GeneratePixelBlender("Overlay"); - GeneratePixelBlender("HardLight"); - - GeneratePixelBlender("Src"); - GeneratePixelBlender("Atop"); - GeneratePixelBlender("Over"); - GeneratePixelBlender("In"); - GeneratePixelBlender("Out"); - GeneratePixelBlender("Dest"); - GeneratePixelBlender("DestAtop"); - GeneratePixelBlender("DestOver"); - GeneratePixelBlender("DestIn"); - GeneratePixelBlender("DestOut"); - GeneratePixelBlender("Clear"); - GeneratePixelBlender("Xor"); +GenerateVectorCompositor("Src", "source", "Vector4.Zero", "xform"); +GenerateVectorCompositor("SrcAtop", "Vector4.Zero", "backdrop", "xform"); +GenerateVectorCompositor("SrcOver", "source", "backdrop", "xform"); +GenerateVectorCompositor("SrcIn", "Vector4.Zero", "Vector4.Zero", "xform"); +GenerateVectorCompositor("SrcOut", "source", "Vector4.Zero", "Vector4.Zero"); +GenerateVectorCompositor("Dest", "Vector4.Zero", "backdrop", "backdrop"); +GenerateVectorCompositor("DestAtop", "source", "Vector4.Zero", "backdrop"); +GenerateVectorCompositor("DestOver", "source", "backdrop", "backdrop"); +GenerateVectorCompositor("DestIn", "Vector4.Zero", "Vector4.Zero", "backdrop"); +GenerateVectorCompositor("DestOut", "Vector4.Zero", "backdrop", "Vector4.Zero"); +GenerateVectorCompositor("Clear", "Vector4.Zero", "Vector4.Zero", "Vector4.Zero"); +GenerateVectorCompositor("Xor", "source", "backdrop", "Vector4.Zero"); +#> + + #endregion + + #region Blenders + +<# +string[] composers = new []{ + "Src" , + "SrcAtop" , + "SrcOver" , + "SrcIn" , + "SrcOut" , + "Dest" , + "DestAtop" , + "DestOver" , + "DestIn" , + "DestOut" , + "Clear" , + "Xor" , +}; +string[] blenders = new []{ + "Normal" , + "Multiply" , + "Add" , + "Subtract" , + "Screen" , + "Darken" , + "Lighten" , + "Overlay" , + "HardLight" +}; +foreach(var composer in composers) +{ + foreach(var blender in blenders) + { + GeneratePixelBlender(blender,composer); + + } +} #> + + #endregion } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.cs b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.cs index c47ef35a3d..b5e89dbec8 100644 --- a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.cs +++ b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.cs @@ -1,194 +1,179 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Numerics; -using System.Runtime.CompilerServices; - -namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders -{ - /// - /// Collection of Porter Duff alpha blending functions applying an the 'Over' composition model. - /// - /// - /// These functions are designed to be a general solution for all color cases, - /// that is, they take in account the alpha value of both the backdrop - /// and source, and there's no need to alpha-premultiply neither the backdrop - /// nor the source. - /// Note there are faster functions for when the backdrop color is known - /// to be opaque - /// - internal static partial class PorterDuffFunctions - { - /// - /// Source over backdrop - /// - /// Backdrop color - /// Source color - /// Opacity applied to Source Alpha - /// Output color - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 Normal(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - return Compose(backdrop, source, source); - } - - /// - /// Source multiplied by backdrop - /// - /// Backdrop color - /// Source color - /// Opacity applied to Source Alpha - /// Output color - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 Multiply(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - return Compose(backdrop, source, backdrop * source); - } - - /// - /// Source added to backdrop - /// - /// Backdrop color - /// Source color - /// Opacity applied to Source Alpha - /// Output color - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 Add(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - return Compose(backdrop, source, Vector4.Min(Vector4.One, backdrop + source)); - } - - /// - /// Source subtracted from backdrop - /// - /// Backdrop color - /// Source color - /// Opacity applied to Source Alpha - /// Output color - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 Subtract(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - return Compose(backdrop, source, Vector4.Max(Vector4.Zero, backdrop - source)); - } - - /// - /// Complement of source multiplied by the complement of backdrop - /// - /// Backdrop color - /// Source color - /// Opacity applied to Source Alpha - /// Output color - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 Screen(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - return Compose(backdrop, source, Vector4.One - ((Vector4.One - backdrop) * (Vector4.One - source))); - } - - /// - /// Per element, chooses the smallest value of source and backdrop - /// - /// Backdrop color - /// Source color - /// Opacity applied to Source Alpha - /// Output color - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 Darken(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - return Compose(backdrop, source, Vector4.Min(backdrop, source)); - } - - /// - /// Per element, chooses the largest value of source and backdrop - /// - /// Backdrop color - /// Source color - /// Opacity applied to Source Alpha - /// Output color - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 Lighten(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - return Compose(backdrop, source, Vector4.Max(backdrop, source)); - } - - /// - /// Overlays source over backdrop - /// - /// Backdrop color - /// Source color - /// Opacity applied to Source Alpha - /// Output color - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 Overlay(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - float cr = OverlayValueFunction(backdrop.X, source.X); - float cg = OverlayValueFunction(backdrop.Y, source.Y); - float cb = OverlayValueFunction(backdrop.Z, source.Z); - - return Compose(backdrop, source, Vector4.Min(Vector4.One, new Vector4(cr, cg, cb, 0))); - } - - /// - /// Hard light effect - /// - /// Backdrop color - /// Source color - /// Opacity applied to Source Alpha - /// Output color - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 HardLight(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - float cr = OverlayValueFunction(source.X, backdrop.X); - float cg = OverlayValueFunction(source.Y, backdrop.Y); - float cb = OverlayValueFunction(source.Z, backdrop.Z); - - return Compose(backdrop, source, Vector4.Min(Vector4.One, new Vector4(cr, cg, cb, 0))); - } - - /// - /// Helper function for Overlay andHardLight modes - /// - /// Backdrop color element - /// Source color element - /// Overlay value - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static float OverlayValueFunction(float backdrop, float source) - { - return backdrop <= 0.5f ? (2 * backdrop * source) : 1 - ((2 * (1 - source)) * (1 - backdrop)); - } - - /// - /// General composition function for all modes, with a general solution for alpha channel - /// - /// Original Backdrop color - /// Original source color - /// Desired transformed color, without taking Alpha channel in account - /// The final color - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vector4 Compose(Vector4 backdrop, Vector4 source, Vector4 xform) - { - // calculate weights - float xw = backdrop.W * source.W; - float bw = backdrop.W - xw; - float sw = source.W - xw; - - // calculate final alpha - float a = xw + bw + sw; - - // calculate final value - xform = ((xform * xw) + (backdrop * bw) + (source * sw)) / MathF.Max(a, Constants.Epsilon); - xform.W = a; - - return xform; - } - } +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Numerics; +using System.Runtime.CompilerServices; + +namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders +{ + /// + /// Collection of Porter Duff alpha blending functions applying an the 'Over' composition model. + /// + /// + /// These functions are designed to be a general solution for all color cases, + /// that is, they take in account the alpha value of both the backdrop + /// and source, and there's no need to alpha-premultiply neither the backdrop + /// nor the source. + /// Note there are faster functions for when the backdrop color is known + /// to be opaque + /// + internal static partial class PorterDuffFunctions + { + /// + /// Source over backdrop + /// + /// Backdrop color + /// Source color + /// Output color + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Normal(Vector4 backdrop, Vector4 source) + { + return source; + } + + /// + /// Source multiplied by backdrop + /// + /// Backdrop color + /// Source color + /// Output color + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Multiply(Vector4 backdrop, Vector4 source) + { + return backdrop * source; + } + + /// + /// Source added to backdrop + /// + /// Backdrop color + /// Source color + /// Output color + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Add(Vector4 backdrop, Vector4 source) + { + return Vector4.Min(Vector4.One, backdrop + source); + } + + /// + /// Source subtracted from backdrop + /// + /// Backdrop color + /// Source color + /// Output color + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Subtract(Vector4 backdrop, Vector4 source) + { + return Vector4.Max(Vector4.Zero, backdrop - source); + } + + /// + /// Complement of source multiplied by the complement of backdrop + /// + /// Backdrop color + /// Source color + /// Output color + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Screen(Vector4 backdrop, Vector4 source) + { + return Vector4.One - ((Vector4.One - backdrop) * (Vector4.One - source)); + } + + /// + /// Per element, chooses the smallest value of source and backdrop + /// + /// Backdrop color + /// Source color + /// Output color + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Darken(Vector4 backdrop, Vector4 source) + { + return Vector4.Min(backdrop, source); + } + + /// + /// Per element, chooses the largest value of source and backdrop + /// + /// Backdrop color + /// Source color + /// Output color + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Lighten(Vector4 backdrop, Vector4 source) + { + return Vector4.Max(backdrop, source); + } + + /// + /// Overlays source over backdrop + /// + /// Backdrop color + /// Source color + /// Output color + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Overlay(Vector4 backdrop, Vector4 source) + { + float cr = OverlayValueFunction(backdrop.X, source.X); + float cg = OverlayValueFunction(backdrop.Y, source.Y); + float cb = OverlayValueFunction(backdrop.Z, source.Z); + + return Vector4.Min(Vector4.One, new Vector4(cr, cg, cb, 0)); + } + + /// + /// Hard light effect + /// + /// Backdrop color + /// Source color + /// Output color + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 HardLight(Vector4 backdrop, Vector4 source) + { + float cr = OverlayValueFunction(source.X, backdrop.X); + float cg = OverlayValueFunction(source.Y, backdrop.Y); + float cb = OverlayValueFunction(source.Z, backdrop.Z); + + return Vector4.Min(Vector4.One, new Vector4(cr, cg, cb, 0)); + } + + /// + /// Helper function for Overlay andHardLight modes + /// + /// Backdrop color element + /// Source color element + /// Overlay value + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static float OverlayValueFunction(float backdrop, float source) + { + return backdrop <= 0.5f ? (2 * backdrop * source) : 1 - ((2 * (1 - source)) * (1 - backdrop)); + } + + /// + /// General composition function for all modes, with a general solution for alpha channel + /// + /// Original Backdrop color + /// Original source color + /// Desired transformed color, without taking Alpha channel in account + /// The final color + /// + /// This is the default compositor for "normal" alpha blending, which matches the generated SrcOver compositor. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Vector4 Compose(Vector4 backdrop, Vector4 source, Vector4 xform) + { + // calculate weights + float xw = backdrop.W * source.W; + float bw = backdrop.W - xw; + float sw = source.W - xw; + + // calculate final alpha + float a = xw + bw + sw; + + // calculate final value + xform = ((xform * xw) + (backdrop * bw) + (source * sw)) / MathF.Max(a, Constants.Epsilon); + xform.W = a; + + return xform; + } + } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.PixelBenders.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.PixelBenders.cs index 2c225ba4c4..ad9366bc52 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.PixelBenders.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.PixelBenders.cs @@ -20,30 +20,30 @@ namespace SixLabors.ImageSharp.PixelFormats { switch (mode) { - case PixelBlenderMode.Multiply: return DefaultPixelBlenders.Multiply.Instance; - case PixelBlenderMode.Add: return DefaultPixelBlenders.Add.Instance; - case PixelBlenderMode.Subtract: return DefaultPixelBlenders.Subtract.Instance; - case PixelBlenderMode.Screen: return DefaultPixelBlenders.Screen.Instance; - case PixelBlenderMode.Darken: return DefaultPixelBlenders.Darken.Instance; - case PixelBlenderMode.Lighten: return DefaultPixelBlenders.Lighten.Instance; - case PixelBlenderMode.Overlay: return DefaultPixelBlenders.Overlay.Instance; - case PixelBlenderMode.HardLight: return DefaultPixelBlenders.HardLight.Instance; - case PixelBlenderMode.Src: return DefaultPixelBlenders.Src.Instance; - case PixelBlenderMode.Atop: return DefaultPixelBlenders.Atop.Instance; - case PixelBlenderMode.Over: return DefaultPixelBlenders.Over.Instance; - case PixelBlenderMode.In: return DefaultPixelBlenders.In.Instance; - case PixelBlenderMode.Out: return DefaultPixelBlenders.Out.Instance; - case PixelBlenderMode.Dest: return DefaultPixelBlenders.Dest.Instance; - case PixelBlenderMode.DestAtop: return DefaultPixelBlenders.DestAtop.Instance; - case PixelBlenderMode.DestOver: return DefaultPixelBlenders.DestOver.Instance; - case PixelBlenderMode.DestIn: return DefaultPixelBlenders.DestIn.Instance; - case PixelBlenderMode.DestOut: return DefaultPixelBlenders.DestOut.Instance; - case PixelBlenderMode.Clear: return DefaultPixelBlenders.Clear.Instance; - case PixelBlenderMode.Xor: return DefaultPixelBlenders.Xor.Instance; + case PixelBlenderMode.Multiply: return DefaultPixelBlenders.Multiply_SrcOver.Instance; + case PixelBlenderMode.Add: return DefaultPixelBlenders.Add_SrcOver.Instance; + case PixelBlenderMode.Subtract: return DefaultPixelBlenders.Subtract_SrcOver.Instance; + case PixelBlenderMode.Screen: return DefaultPixelBlenders.Screen_SrcOver.Instance; + case PixelBlenderMode.Darken: return DefaultPixelBlenders.Darken_SrcOver.Instance; + case PixelBlenderMode.Lighten: return DefaultPixelBlenders.Lighten_SrcOver.Instance; + case PixelBlenderMode.Overlay: return DefaultPixelBlenders.Overlay_SrcOver.Instance; + case PixelBlenderMode.HardLight: return DefaultPixelBlenders.HardLight_SrcOver.Instance; + case PixelBlenderMode.Src: return DefaultPixelBlenders.Normal_Src.Instance; + case PixelBlenderMode.Atop: return DefaultPixelBlenders.Normal_SrcAtop.Instance; + case PixelBlenderMode.Over: return DefaultPixelBlenders.Normal_SrcOver.Instance; + case PixelBlenderMode.In: return DefaultPixelBlenders.Normal_SrcIn.Instance; + case PixelBlenderMode.Out: return DefaultPixelBlenders.Normal_SrcOut.Instance; + case PixelBlenderMode.Dest: return DefaultPixelBlenders.Normal_Dest.Instance; + case PixelBlenderMode.DestAtop: return DefaultPixelBlenders.Normal_DestAtop.Instance; + case PixelBlenderMode.DestOver: return DefaultPixelBlenders.Normal_DestOver.Instance; + case PixelBlenderMode.DestIn: return DefaultPixelBlenders.Normal_DestIn.Instance; + case PixelBlenderMode.DestOut: return DefaultPixelBlenders.Normal_DestOut.Instance; + case PixelBlenderMode.Clear: return DefaultPixelBlenders.Normal_Clear.Instance; + case PixelBlenderMode.Xor: return DefaultPixelBlenders.Normal_Xor.Instance; case PixelBlenderMode.Normal: default: - return DefaultPixelBlenders.Normal.Instance; + return DefaultPixelBlenders.Normal_SrcOver.Instance; } } } diff --git a/tests/ImageSharp.Benchmarks/PixelBlenders/PorterDuffBulkVsPixel.cs b/tests/ImageSharp.Benchmarks/PixelBlenders/PorterDuffBulkVsPixel.cs index 5fe8b2785d..df7e5b4135 100644 --- a/tests/ImageSharp.Benchmarks/PixelBlenders/PorterDuffBulkVsPixel.cs +++ b/tests/ImageSharp.Benchmarks/PixelBlenders/PorterDuffBulkVsPixel.cs @@ -35,7 +35,7 @@ namespace SixLabors.ImageSharp.Benchmarks for (int i = 0; i < destination.Length; i++) { - destinationSpan[i] = PorterDuffFunctions.Normal(backgroundSpan[i], sourceSpan[i], amount[i]); + destinationSpan[i] = PorterDuffFunctions.Normal_SrcOver(backgroundSpan[i], sourceSpan[i], amount[i]); } PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); @@ -50,7 +50,7 @@ namespace SixLabors.ImageSharp.Benchmarks for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.Normal(destination[i], source[i], amount[i]); + destination[i] = PorterDuffFunctions.Normal_SrcOver(destination[i], source[i], amount[i]); } } diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelBlenders/PorterDuffFunctionsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelBlenders/PorterDuffFunctionsTests.cs index c5910e13a3..c34bdc56e4 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelBlenders/PorterDuffFunctionsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelBlenders/PorterDuffFunctionsTests.cs @@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders [MemberData(nameof(NormalBlendFunctionData))] public void NormalBlendFunction(TestVector4 back, TestVector4 source, float amount, TestVector4 expected) { - Vector4 actual = PorterDuffFunctions.Normal((Vector4)back, source, amount); + Vector4 actual = PorterDuffFunctions.Normal_SrcOver((Vector4)back, source, amount); Assert.Equal(expected, actual); } @@ -41,7 +41,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders [MemberData(nameof(MultiplyFunctionData))] public void MultiplyFunction(TestVector4 back, TestVector4 source, float amount, TestVector4 expected) { - Vector4 actual = PorterDuffFunctions.Multiply((Vector4)back, source, amount); + Vector4 actual = PorterDuffFunctions.Multiply_SrcOver((Vector4)back, source, amount); VectorAssert.Equal(expected, actual, 5); } @@ -60,7 +60,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders [MemberData(nameof(AddFunctionData))] public void AddFunction(TestVector4 back, TestVector4 source, float amount, TestVector4 expected) { - Vector4 actual = PorterDuffFunctions.Multiply((Vector4)back, source, amount); + Vector4 actual = PorterDuffFunctions.Multiply_SrcOver((Vector4)back, source, amount); VectorAssert.Equal(expected, actual, 5); } @@ -79,7 +79,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders [MemberData(nameof(SubstractFunctionData))] public void SubstractFunction(TestVector4 back, TestVector4 source, float amount, TestVector4 expected) { - Vector4 actual = PorterDuffFunctions.Subtract((Vector4)back, source, amount); + Vector4 actual = PorterDuffFunctions.Subtract_SrcOver((Vector4)back, source, amount); VectorAssert.Equal(expected, actual, 5); } @@ -98,7 +98,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders [MemberData(nameof(ScreenFunctionData))] public void ScreenFunction(TestVector4 back, TestVector4 source, float amount, TestVector4 expected) { - Vector4 actual = PorterDuffFunctions.Screen((Vector4)back, source, amount); + Vector4 actual = PorterDuffFunctions.Screen_SrcOver((Vector4)back, source, amount); VectorAssert.Equal(expected, actual, 5); } @@ -117,7 +117,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders [MemberData(nameof(DarkenFunctionData))] public void DarkenFunction(TestVector4 back, TestVector4 source, float amount, TestVector4 expected) { - Vector4 actual = PorterDuffFunctions.Darken((Vector4)back, source, amount); + Vector4 actual = PorterDuffFunctions.Darken_SrcOver((Vector4)back, source, amount); VectorAssert.Equal(expected, actual, 5); } @@ -136,7 +136,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders [MemberData(nameof(LightenFunctionData))] public void LightenFunction(TestVector4 back, TestVector4 source, float amount, TestVector4 expected) { - Vector4 actual = PorterDuffFunctions.Lighten((Vector4)back, source, amount); + Vector4 actual = PorterDuffFunctions.Lighten_SrcOver((Vector4)back, source, amount); VectorAssert.Equal(expected, actual, 5); } @@ -155,7 +155,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders [MemberData(nameof(OverlayFunctionData))] public void OverlayFunction(TestVector4 back, TestVector4 source, float amount, TestVector4 expected) { - Vector4 actual = PorterDuffFunctions.Overlay((Vector4)back, source, amount); + Vector4 actual = PorterDuffFunctions.Overlay_SrcOver((Vector4)back, source, amount); VectorAssert.Equal(expected, actual, 5); } @@ -174,7 +174,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders [MemberData(nameof(HardLightFunctionData))] public void HardLightFunction(TestVector4 back, TestVector4 source, float amount, TestVector4 expected) { - Vector4 actual = PorterDuffFunctions.HardLight((Vector4)back, source, amount); + Vector4 actual = PorterDuffFunctions.HardLight_SrcOver((Vector4)back, source, amount); VectorAssert.Equal(expected, actual, 5); } } diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelBlenders/PorterDuffFunctionsTests_TPixel.cs b/tests/ImageSharp.Tests/PixelFormats/PixelBlenders/PorterDuffFunctionsTests_TPixel.cs index 1273a453ea..a53591dbc2 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelBlenders/PorterDuffFunctionsTests_TPixel.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelBlenders/PorterDuffFunctionsTests_TPixel.cs @@ -34,7 +34,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders public void NormalBlendFunction(TestPixel back, TestPixel source, float amount, TestPixel expected) where TPixel : struct, IPixel { - TPixel actual = PorterDuffFunctions.Normal((TPixel)(TPixel)back, source, amount); + TPixel actual = PorterDuffFunctions.Normal_SrcOver((TPixel)(TPixel)back, source, amount); VectorAssert.Equal(expected, actual, 2); } @@ -43,7 +43,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders public void NormalBlendFunction_Blender(TestPixel back, TestPixel source, float amount, TestPixel expected) where TPixel : struct, IPixel { - TPixel actual = new DefaultPixelBlenders.Normal().Blend(back, source, amount); + TPixel actual = new DefaultPixelBlenders.Normal_SrcOver().Blend(back, source, amount); VectorAssert.Equal(expected, actual, 2); } @@ -53,7 +53,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders where TPixel : struct, IPixel { Span dest = new Span(new TPixel[1]); - new DefaultPixelBlenders.Normal().Blend(this.MemoryAllocator, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); + new DefaultPixelBlenders.Normal_SrcOver().Blend(this.MemoryAllocator, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); VectorAssert.Equal(expected, dest[0], 2); } @@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders public void MultiplyFunction(TestPixel back, TestPixel source, float amount, TestPixel expected) where TPixel : struct, IPixel { - TPixel actual = PorterDuffFunctions.Multiply((TPixel)back, source, amount); + TPixel actual = PorterDuffFunctions.Multiply_SrcOver((TPixel)back, source, amount); VectorAssert.Equal(expected, actual, 2); } @@ -82,7 +82,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders public void MultiplyFunction_Blender(TestPixel back, TestPixel source, float amount, TestPixel expected) where TPixel : struct, IPixel { - TPixel actual = new DefaultPixelBlenders.Multiply().Blend(back, source, amount); + TPixel actual = new DefaultPixelBlenders.Multiply_SrcOver().Blend(back, source, amount); VectorAssert.Equal(expected, actual, 2); } @@ -92,7 +92,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders where TPixel : struct, IPixel { Span dest = new Span(new TPixel[1]); - new DefaultPixelBlenders.Multiply().Blend(this.MemoryAllocator, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); + new DefaultPixelBlenders.Multiply_SrcOver().Blend(this.MemoryAllocator, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); VectorAssert.Equal(expected, dest[0], 2); } @@ -112,7 +112,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders public void AddFunction(TestPixel back, TestPixel source, float amount, TestPixel expected) where TPixel : struct, IPixel { - TPixel actual = PorterDuffFunctions.Add((TPixel)back, source, amount); + TPixel actual = PorterDuffFunctions.Add_SrcOver((TPixel)back, source, amount); VectorAssert.Equal(expected, actual, 2); } @@ -121,7 +121,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders public void AddFunction_Blender(TestPixel back, TestPixel source, float amount, TestPixel expected) where TPixel : struct, IPixel { - TPixel actual = new DefaultPixelBlenders.Add().Blend(back, source, amount); + TPixel actual = new DefaultPixelBlenders.Add_SrcOver().Blend(back, source, amount); VectorAssert.Equal(expected, actual, 2); } @@ -131,7 +131,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders where TPixel : struct, IPixel { Span dest = new Span(new TPixel[1]); - new DefaultPixelBlenders.Add().Blend(this.MemoryAllocator, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); + new DefaultPixelBlenders.Add_SrcOver().Blend(this.MemoryAllocator, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); VectorAssert.Equal(expected, dest[0], 2); } @@ -151,7 +151,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders public void SubstractFunction(TestPixel back, TestPixel source, float amount, TestPixel expected) where TPixel : struct, IPixel { - TPixel actual = PorterDuffFunctions.Subtract((TPixel)back, source, amount); + TPixel actual = PorterDuffFunctions.Subtract_SrcOver((TPixel)back, source, amount); VectorAssert.Equal(expected, actual, 2); } @@ -160,7 +160,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders public void SubstractFunction_Blender(TestPixel back, TestPixel source, float amount, TestPixel expected) where TPixel : struct, IPixel { - TPixel actual = new DefaultPixelBlenders.Subtract().Blend(back, source, amount); + TPixel actual = new DefaultPixelBlenders.Subtract_SrcOver().Blend(back, source, amount); VectorAssert.Equal(expected, actual, 2); } @@ -170,7 +170,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders where TPixel : struct, IPixel { Span dest = new Span(new TPixel[1]); - new DefaultPixelBlenders.Subtract().Blend(this.MemoryAllocator, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); + new DefaultPixelBlenders.Subtract_SrcOver().Blend(this.MemoryAllocator, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); VectorAssert.Equal(expected, dest[0], 2); } @@ -190,7 +190,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders public void ScreenFunction(TestPixel back, TestPixel source, float amount, TestPixel expected) where TPixel : struct, IPixel { - TPixel actual = PorterDuffFunctions.Screen((TPixel)back, source, amount); + TPixel actual = PorterDuffFunctions.Screen_SrcOver((TPixel)back, source, amount); VectorAssert.Equal(expected, actual, 2); } @@ -199,7 +199,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders public void ScreenFunction_Blender(TestPixel back, TestPixel source, float amount, TestPixel expected) where TPixel : struct, IPixel { - TPixel actual = new DefaultPixelBlenders.Screen().Blend(back, source, amount); + TPixel actual = new DefaultPixelBlenders.Screen_SrcOver().Blend(back, source, amount); VectorAssert.Equal(expected, actual, 2); } @@ -209,7 +209,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders where TPixel : struct, IPixel { Span dest = new Span(new TPixel[1]); - new DefaultPixelBlenders.Screen().Blend(this.MemoryAllocator, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); + new DefaultPixelBlenders.Screen_SrcOver().Blend(this.MemoryAllocator, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); VectorAssert.Equal(expected, dest[0], 2); } @@ -229,7 +229,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders public void DarkenFunction(TestPixel back, TestPixel source, float amount, TestPixel expected) where TPixel : struct, IPixel { - TPixel actual = PorterDuffFunctions.Darken((TPixel)back, source, amount); + TPixel actual = PorterDuffFunctions.Darken_SrcOver((TPixel)back, source, amount); VectorAssert.Equal(expected, actual, 2); } @@ -238,7 +238,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders public void DarkenFunction_Blender(TestPixel back, TestPixel source, float amount, TestPixel expected) where TPixel : struct, IPixel { - TPixel actual = new DefaultPixelBlenders.Darken().Blend(back, source, amount); + TPixel actual = new DefaultPixelBlenders.Darken_SrcOver().Blend(back, source, amount); VectorAssert.Equal(expected, actual, 2); } @@ -248,7 +248,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders where TPixel : struct, IPixel { Span dest = new Span(new TPixel[1]); - new DefaultPixelBlenders.Darken().Blend(this.MemoryAllocator, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); + new DefaultPixelBlenders.Darken_SrcOver().Blend(this.MemoryAllocator, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); VectorAssert.Equal(expected, dest[0], 2); } @@ -268,7 +268,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders public void LightenFunction(TestPixel back, TestPixel source, float amount, TestPixel expected) where TPixel : struct, IPixel { - TPixel actual = PorterDuffFunctions.Lighten((TPixel)back, source, amount); + TPixel actual = PorterDuffFunctions.Lighten_SrcOver((TPixel)back, source, amount); VectorAssert.Equal(expected, actual, 2); } @@ -277,7 +277,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders public void LightenFunction_Blender(TestPixel back, TestPixel source, float amount, TestPixel expected) where TPixel : struct, IPixel { - TPixel actual = new DefaultPixelBlenders.Lighten().Blend(back, source, amount); + TPixel actual = new DefaultPixelBlenders.Lighten_SrcOver().Blend(back, source, amount); VectorAssert.Equal(expected, actual, 2); } @@ -287,7 +287,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders where TPixel : struct, IPixel { Span dest = new Span(new TPixel[1]); - new DefaultPixelBlenders.Lighten().Blend(this.MemoryAllocator, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); + new DefaultPixelBlenders.Lighten_SrcOver().Blend(this.MemoryAllocator, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); VectorAssert.Equal(expected, dest[0], 2); } @@ -307,7 +307,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders public void OverlayFunction(TestPixel back, TestPixel source, float amount, TestPixel expected) where TPixel : struct, IPixel { - TPixel actual = PorterDuffFunctions.Overlay((TPixel)back, source, amount); + TPixel actual = PorterDuffFunctions.Overlay_SrcOver((TPixel)back, source, amount); VectorAssert.Equal(expected, actual, 2); } @@ -316,7 +316,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders public void OverlayFunction_Blender(TestPixel back, TestPixel source, float amount, TestPixel expected) where TPixel : struct, IPixel { - TPixel actual = new DefaultPixelBlenders.Overlay().Blend(back, source, amount); + TPixel actual = new DefaultPixelBlenders.Overlay_SrcOver().Blend(back, source, amount); VectorAssert.Equal(expected, actual, 2); } @@ -326,7 +326,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders where TPixel : struct, IPixel { Span dest = new Span(new TPixel[1]); - new DefaultPixelBlenders.Overlay().Blend(this.MemoryAllocator, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); + new DefaultPixelBlenders.Overlay_SrcOver().Blend(this.MemoryAllocator, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); VectorAssert.Equal(expected, dest[0], 2); } @@ -346,7 +346,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders public void HardLightFunction(TestPixel back, TestPixel source, float amount, TestPixel expected) where TPixel : struct, IPixel { - TPixel actual = PorterDuffFunctions.HardLight((TPixel)back, source, amount); + TPixel actual = PorterDuffFunctions.HardLight_SrcOver((TPixel)back, source, amount); VectorAssert.Equal(expected, actual, 2); } @@ -355,7 +355,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders public void HardLightFunction_Blender(TestPixel back, TestPixel source, float amount, TestPixel expected) where TPixel : struct, IPixel { - TPixel actual = new DefaultPixelBlenders.HardLight().Blend(back, source, amount); + TPixel actual = new DefaultPixelBlenders.HardLight_SrcOver().Blend(back, source, amount); VectorAssert.Equal(expected, actual, 2); } @@ -365,7 +365,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders where TPixel : struct, IPixel { Span dest = new Span(new TPixel[1]); - new DefaultPixelBlenders.HardLight().Blend(this.MemoryAllocator, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); + new DefaultPixelBlenders.HardLight_SrcOver().Blend(this.MemoryAllocator, dest, back.AsSpan(), source.AsSpan(), AsSpan(amount)); VectorAssert.Equal(expected, dest[0], 2); } } diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.Blender.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.Blender.cs index d3956ecd5d..1a4121c974 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.Blender.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.Blender.cs @@ -17,50 +17,50 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats public static TheoryData BlenderMappings = new TheoryData() { - { new TestPixel(), typeof(DefaultPixelBlenders.Normal), PixelBlenderMode.Normal }, - { new TestPixel(), typeof(DefaultPixelBlenders.Screen), PixelBlenderMode.Screen }, - { new TestPixel(), typeof(DefaultPixelBlenders.HardLight), PixelBlenderMode.HardLight }, - { new TestPixel(), typeof(DefaultPixelBlenders.Overlay), PixelBlenderMode.Overlay }, - { new TestPixel(), typeof(DefaultPixelBlenders.Darken), PixelBlenderMode.Darken }, - { new TestPixel(), typeof(DefaultPixelBlenders.Lighten), PixelBlenderMode.Lighten }, - { new TestPixel(), typeof(DefaultPixelBlenders.Add), PixelBlenderMode.Add }, - { new TestPixel(), typeof(DefaultPixelBlenders.Subtract), PixelBlenderMode.Subtract }, - { new TestPixel(), typeof(DefaultPixelBlenders.Multiply), PixelBlenderMode.Multiply }, + { new TestPixel(), typeof(DefaultPixelBlenders.Normal_SrcOver), PixelBlenderMode.Normal }, + { new TestPixel(), typeof(DefaultPixelBlenders.Screen_SrcOver), PixelBlenderMode.Screen }, + { new TestPixel(), typeof(DefaultPixelBlenders.HardLight_SrcOver), PixelBlenderMode.HardLight }, + { new TestPixel(), typeof(DefaultPixelBlenders.Overlay_SrcOver), PixelBlenderMode.Overlay }, + { new TestPixel(), typeof(DefaultPixelBlenders.Darken_SrcOver), PixelBlenderMode.Darken }, + { new TestPixel(), typeof(DefaultPixelBlenders.Lighten_SrcOver), PixelBlenderMode.Lighten }, + { new TestPixel(), typeof(DefaultPixelBlenders.Add_SrcOver), PixelBlenderMode.Add }, + { new TestPixel(), typeof(DefaultPixelBlenders.Subtract_SrcOver), PixelBlenderMode.Subtract }, + { new TestPixel(), typeof(DefaultPixelBlenders.Multiply_SrcOver), PixelBlenderMode.Multiply }, - { new TestPixel(), typeof(DefaultPixelBlenders.Src), PixelBlenderMode.Src }, - { new TestPixel(), typeof(DefaultPixelBlenders.Atop), PixelBlenderMode.Atop }, - { new TestPixel(), typeof(DefaultPixelBlenders.Over), PixelBlenderMode.Over }, - { new TestPixel(), typeof(DefaultPixelBlenders.In), PixelBlenderMode.In }, - { new TestPixel(), typeof(DefaultPixelBlenders.Out), PixelBlenderMode.Out }, - { new TestPixel(), typeof(DefaultPixelBlenders.Dest), PixelBlenderMode.Dest }, - { new TestPixel(), typeof(DefaultPixelBlenders.DestAtop), PixelBlenderMode.DestAtop }, - { new TestPixel(), typeof(DefaultPixelBlenders.DestOver), PixelBlenderMode.DestOver }, - { new TestPixel(), typeof(DefaultPixelBlenders.DestIn), PixelBlenderMode.DestIn }, - { new TestPixel(), typeof(DefaultPixelBlenders.DestOut), PixelBlenderMode.DestOut }, - { new TestPixel(), typeof(DefaultPixelBlenders.Clear), PixelBlenderMode.Clear }, - { new TestPixel(), typeof(DefaultPixelBlenders.Xor), PixelBlenderMode.Xor }, + { new TestPixel(), typeof(DefaultPixelBlenders.Normal_Src), PixelBlenderMode.Src }, + { new TestPixel(), typeof(DefaultPixelBlenders.Normal_SrcAtop), PixelBlenderMode.Atop }, + { new TestPixel(), typeof(DefaultPixelBlenders.Normal_SrcOver), PixelBlenderMode.Over }, + { new TestPixel(), typeof(DefaultPixelBlenders.Normal_SrcIn), PixelBlenderMode.In }, + { new TestPixel(), typeof(DefaultPixelBlenders.Normal_SrcOut), PixelBlenderMode.Out }, + { new TestPixel(), typeof(DefaultPixelBlenders.Normal_Dest), PixelBlenderMode.Dest }, + { new TestPixel(), typeof(DefaultPixelBlenders.Normal_DestAtop), PixelBlenderMode.DestAtop }, + { new TestPixel(), typeof(DefaultPixelBlenders.Normal_DestOver), PixelBlenderMode.DestOver }, + { new TestPixel(), typeof(DefaultPixelBlenders.Normal_DestIn), PixelBlenderMode.DestIn }, + { new TestPixel(), typeof(DefaultPixelBlenders.Normal_DestOut), PixelBlenderMode.DestOut }, + { new TestPixel(), typeof(DefaultPixelBlenders.Normal_Clear), PixelBlenderMode.Clear }, + { new TestPixel(), typeof(DefaultPixelBlenders.Normal_Xor), PixelBlenderMode.Xor }, - { new TestPixel(), typeof(DefaultPixelBlenders.Normal), PixelBlenderMode.Normal }, - { new TestPixel(), typeof(DefaultPixelBlenders.Screen), PixelBlenderMode.Screen }, - { new TestPixel(), typeof(DefaultPixelBlenders.HardLight), PixelBlenderMode.HardLight }, - { new TestPixel(), typeof(DefaultPixelBlenders.Overlay), PixelBlenderMode.Overlay }, - { new TestPixel(), typeof(DefaultPixelBlenders.Darken), PixelBlenderMode.Darken }, - { new TestPixel(), typeof(DefaultPixelBlenders.Lighten), PixelBlenderMode.Lighten }, - { new TestPixel(), typeof(DefaultPixelBlenders.Add), PixelBlenderMode.Add }, - { new TestPixel(), typeof(DefaultPixelBlenders.Subtract), PixelBlenderMode.Subtract }, - { new TestPixel(), typeof(DefaultPixelBlenders.Multiply), PixelBlenderMode.Multiply }, - { new TestPixel(), typeof(DefaultPixelBlenders.Src), PixelBlenderMode.Src }, - { new TestPixel(), typeof(DefaultPixelBlenders.Atop), PixelBlenderMode.Atop }, - { new TestPixel(), typeof(DefaultPixelBlenders.Over), PixelBlenderMode.Over }, - { new TestPixel(), typeof(DefaultPixelBlenders.In), PixelBlenderMode.In }, - { new TestPixel(), typeof(DefaultPixelBlenders.Out), PixelBlenderMode.Out }, - { new TestPixel(), typeof(DefaultPixelBlenders.Dest), PixelBlenderMode.Dest }, - { new TestPixel(), typeof(DefaultPixelBlenders.DestAtop), PixelBlenderMode.DestAtop }, - { new TestPixel(), typeof(DefaultPixelBlenders.DestOver), PixelBlenderMode.DestOver }, - { new TestPixel(), typeof(DefaultPixelBlenders.DestIn), PixelBlenderMode.DestIn }, - { new TestPixel(), typeof(DefaultPixelBlenders.DestOut), PixelBlenderMode.DestOut }, - { new TestPixel(), typeof(DefaultPixelBlenders.Clear), PixelBlenderMode.Clear }, - { new TestPixel(), typeof(DefaultPixelBlenders.Xor), PixelBlenderMode.Xor }, + { new TestPixel(), typeof(DefaultPixelBlenders.Normal_SrcOver), PixelBlenderMode.Normal }, + { new TestPixel(), typeof(DefaultPixelBlenders.Screen_SrcOver), PixelBlenderMode.Screen }, + { new TestPixel(), typeof(DefaultPixelBlenders.HardLight_SrcOver), PixelBlenderMode.HardLight }, + { new TestPixel(), typeof(DefaultPixelBlenders.Overlay_SrcOver), PixelBlenderMode.Overlay }, + { new TestPixel(), typeof(DefaultPixelBlenders.Darken_SrcOver), PixelBlenderMode.Darken }, + { new TestPixel(), typeof(DefaultPixelBlenders.Lighten_SrcOver), PixelBlenderMode.Lighten }, + { new TestPixel(), typeof(DefaultPixelBlenders.Add_SrcOver), PixelBlenderMode.Add }, + { new TestPixel(), typeof(DefaultPixelBlenders.Subtract_SrcOver), PixelBlenderMode.Subtract }, + { new TestPixel(), typeof(DefaultPixelBlenders.Multiply_SrcOver), PixelBlenderMode.Multiply }, + { new TestPixel(), typeof(DefaultPixelBlenders.Normal_Src), PixelBlenderMode.Src }, + { new TestPixel(), typeof(DefaultPixelBlenders.Normal_SrcAtop), PixelBlenderMode.Atop }, + { new TestPixel(), typeof(DefaultPixelBlenders.Normal_SrcOver), PixelBlenderMode.Over }, + { new TestPixel(), typeof(DefaultPixelBlenders.Normal_SrcIn), PixelBlenderMode.In }, + { new TestPixel(), typeof(DefaultPixelBlenders.Normal_SrcOut), PixelBlenderMode.Out }, + { new TestPixel(), typeof(DefaultPixelBlenders.Normal_Dest), PixelBlenderMode.Dest }, + { new TestPixel(), typeof(DefaultPixelBlenders.Normal_DestAtop), PixelBlenderMode.DestAtop }, + { new TestPixel(), typeof(DefaultPixelBlenders.Normal_DestOver), PixelBlenderMode.DestOver }, + { new TestPixel(), typeof(DefaultPixelBlenders.Normal_DestIn), PixelBlenderMode.DestIn }, + { new TestPixel(), typeof(DefaultPixelBlenders.Normal_DestOut), PixelBlenderMode.DestOut }, + { new TestPixel(), typeof(DefaultPixelBlenders.Normal_Clear), PixelBlenderMode.Clear }, + { new TestPixel(), typeof(DefaultPixelBlenders.Normal_Xor), PixelBlenderMode.Xor }, };