From 53c67b23873e22d83f21fb237d41ea71fcf43879 Mon Sep 17 00:00:00 2001 From: Scott Williams Date: Sun, 18 Jun 2017 12:40:47 +0100 Subject: [PATCH] ensure older blenders function as before --- .../PorterDuffFunctions.Generated.cs | 205 ++++++++++++++++-- .../PorterDuffFunctions.Generated.tt | 27 ++- .../PixelBlenders/PorterDuffFunctions.cs | 32 +-- 3 files changed, 221 insertions(+), 43 deletions(-) diff --git a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.cs b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.cs index a2cbb0719..4213be0ba 100644 --- a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.cs @@ -12,83 +12,250 @@ namespace ImageSharp.PixelFormats.PixelBlenders internal static partial class PorterDuffFunctions { - [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Src(Vector4 backdrop, Vector4 source, float opacity) { - source.W *= opacity; - return Compose(Vector4.Zero, source, source).Blend(backdrop, opacity); + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + Vector4 xform = source; + + // calculate weights + float xw = Vector4.Zero.W * source.W; + float bw = Vector4.Zero.W - xw; + float sw = source.W - xw; + + // calculate final alpha + float a = xw + bw + sw; + + // calculate final value + xform = ((xform * xw) + (Vector4.Zero * bw) + (source * sw)) / MathF.Max(a, Constants.Epsilon); + + return Vector4.Lerp(backdrop, xform, opacity); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Atop(Vector4 backdrop, Vector4 source, float opacity) { - return Compose(backdrop, Vector4.Zero, source).Blend(backdrop, opacity); + opacity = opacity.Clamp(0, 1); + Vector4 xform = source; + + // calculate weights + float xw = backdrop.W * Vector4.Zero.W; + float bw = backdrop.W - xw; + float sw = Vector4.Zero.W - xw; + + // calculate final alpha + float a = xw + bw + sw; + + // calculate final value + xform = ((xform * xw) + (backdrop * bw) + (Vector4.Zero * sw)) / MathF.Max(a, Constants.Epsilon); + + return Vector4.Lerp(backdrop, xform, opacity); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Over(Vector4 backdrop, Vector4 source, float opacity) { - source.W *= opacity; - return Compose(backdrop, source, source).Blend(backdrop, opacity); + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + Vector4 xform = source; + + // 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); + + return Vector4.Lerp(backdrop, xform, opacity); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 In(Vector4 backdrop, Vector4 source, float opacity) { - return Compose(Vector4.Zero, Vector4.Zero, source).Blend(backdrop, opacity); + opacity = opacity.Clamp(0, 1); + Vector4 xform = source; + + // calculate weights + float xw = Vector4.Zero.W * Vector4.Zero.W; + float bw = Vector4.Zero.W - xw; + float sw = Vector4.Zero.W - xw; + + // calculate final alpha + float a = xw + bw + sw; + + // calculate final value + xform = ((xform * xw) + (Vector4.Zero * bw) + (Vector4.Zero * sw)) / MathF.Max(a, Constants.Epsilon); + + return Vector4.Lerp(backdrop, xform, opacity); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Out(Vector4 backdrop, Vector4 source, float opacity) { - source.W *= opacity; - return Compose(Vector4.Zero, source, Vector4.Zero).Blend(backdrop, opacity); + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + Vector4 xform = Vector4.Zero; + + // calculate weights + float xw = Vector4.Zero.W * source.W; + float bw = Vector4.Zero.W - xw; + float sw = source.W - xw; + + // calculate final alpha + float a = xw + bw + sw; + + // calculate final value + xform = ((xform * xw) + (Vector4.Zero * bw) + (source * sw)) / MathF.Max(a, Constants.Epsilon); + + return Vector4.Lerp(backdrop, xform, opacity); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Dest(Vector4 backdrop, Vector4 source, float opacity) { - return Compose(backdrop, Vector4.Zero, backdrop).Blend(backdrop, opacity); + opacity = opacity.Clamp(0, 1); + Vector4 xform = backdrop; + + // calculate weights + float xw = backdrop.W * Vector4.Zero.W; + float bw = backdrop.W - xw; + float sw = Vector4.Zero.W - xw; + + // calculate final alpha + float a = xw + bw + sw; + + // calculate final value + xform = ((xform * xw) + (backdrop * bw) + (Vector4.Zero * sw)) / MathF.Max(a, Constants.Epsilon); + + return Vector4.Lerp(backdrop, xform, opacity); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 DestAtop(Vector4 backdrop, Vector4 source, float opacity) { - source.W *= opacity; - return Compose(Vector4.Zero, source, backdrop).Blend(backdrop, opacity); + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + Vector4 xform = backdrop; + + // calculate weights + float xw = Vector4.Zero.W * source.W; + float bw = Vector4.Zero.W - xw; + float sw = source.W - xw; + + // calculate final alpha + float a = xw + bw + sw; + + // calculate final value + xform = ((xform * xw) + (Vector4.Zero * bw) + (source * sw)) / MathF.Max(a, Constants.Epsilon); + + return Vector4.Lerp(backdrop, xform, opacity); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 DestOver(Vector4 backdrop, Vector4 source, float opacity) { - source.W *= opacity; - return Compose(backdrop, source, backdrop).Blend(backdrop, opacity); + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + Vector4 xform = backdrop; + + // 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); + + return Vector4.Lerp(backdrop, xform, opacity); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 DestIn(Vector4 backdrop, Vector4 source, float opacity) { - return Compose(Vector4.Zero, Vector4.Zero, backdrop).Blend(backdrop, opacity); + opacity = opacity.Clamp(0, 1); + Vector4 xform = backdrop; + + // calculate weights + float xw = Vector4.Zero.W * Vector4.Zero.W; + float bw = Vector4.Zero.W - xw; + float sw = Vector4.Zero.W - xw; + + // calculate final alpha + float a = xw + bw + sw; + + // calculate final value + xform = ((xform * xw) + (Vector4.Zero * bw) + (Vector4.Zero * sw)) / MathF.Max(a, Constants.Epsilon); + + return Vector4.Lerp(backdrop, xform, opacity); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 DestOut(Vector4 backdrop, Vector4 source, float opacity) { - return Compose(backdrop, Vector4.Zero, Vector4.Zero).Blend(backdrop, opacity); + opacity = opacity.Clamp(0, 1); + Vector4 xform = Vector4.Zero; + + // calculate weights + float xw = backdrop.W * Vector4.Zero.W; + float bw = backdrop.W - xw; + float sw = Vector4.Zero.W - xw; + + // calculate final alpha + float a = xw + bw + sw; + + // calculate final value + xform = ((xform * xw) + (backdrop * bw) + (Vector4.Zero * sw)) / MathF.Max(a, Constants.Epsilon); + + return Vector4.Lerp(backdrop, xform, opacity); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Clear(Vector4 backdrop, Vector4 source, float opacity) { - return Compose(Vector4.Zero, Vector4.Zero, Vector4.Zero).Blend(backdrop, opacity); + opacity = opacity.Clamp(0, 1); + Vector4 xform = Vector4.Zero; + + // calculate weights + float xw = Vector4.Zero.W * Vector4.Zero.W; + float bw = Vector4.Zero.W - xw; + float sw = Vector4.Zero.W - xw; + + // calculate final alpha + float a = xw + bw + sw; + + // calculate final value + xform = ((xform * xw) + (Vector4.Zero * bw) + (Vector4.Zero * sw)) / MathF.Max(a, Constants.Epsilon); + + return Vector4.Lerp(backdrop, xform, opacity); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Xor(Vector4 backdrop, Vector4 source, float opacity) { - source.W *= opacity; - return Compose(backdrop, source, Vector4.Zero).Blend(backdrop, opacity); + opacity = opacity.Clamp(0, 1); + source.W *= opacity; + Vector4 xform = Vector4.Zero; + + // 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); + + return Vector4.Lerp(backdrop, xform, opacity); } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.tt b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.tt index 1b60481b6..53d22d8f3 100644 --- a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.tt @@ -24,7 +24,6 @@ namespace ImageSharp.PixelFormats.PixelBlenders internal static partial class PorterDuffFunctions { - <# void GeneratePixelBlender (string blender) @@ -48,18 +47,28 @@ namespace ImageSharp.PixelFormats.PixelBlenders [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 <#=name#>(Vector4 backdrop, Vector4 source, float opacity) { - <# if(sourceVar != "Vector4.Zero") { - #> - <#=sourceVar#>.W *= opacity; - <# - } #> - return Compose(<#=destVar#>, <#=sourceVar#>, <#=blendVar#>).Blend(backdrop, opacity); + opacity = opacity.Clamp(0, 1); +<# if(sourceVar != "Vector4.Zero" ) { #> + source.W *= opacity; +<# } #> + Vector4 xform = <#=blendVar#>; + + // calculate weights + float xw = <#=destVar#>.W * <#=sourceVar#>.W; + float bw = <#=destVar#>.W - xw; + float sw = <#=sourceVar#>.W - xw; + + // calculate final alpha + float a = xw + bw + sw; + + // calculate final value + xform = ((xform * xw) + (<#=destVar#> * bw) + (<#=sourceVar#> * sw)) / MathF.Max(a, Constants.Epsilon); + + return Vector4.Lerp(backdrop, xform, opacity); } <# } - - GenerateVectorCompositor("Src", "source", "Vector4.Zero", "source"); GenerateVectorCompositor("Atop", "Vector4.Zero", "backdrop", "source"); GenerateVectorCompositor("Over", "source", "backdrop", "source"); diff --git a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.cs b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.cs index bc7bb2d90..b1fca9520 100644 --- a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.cs +++ b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.cs @@ -31,7 +31,8 @@ namespace ImageSharp.PixelFormats.PixelBlenders [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Normal(Vector4 backdrop, Vector4 source, float opacity) { - return Over(backdrop, source, opacity); + source.W *= opacity; + return Compose(backdrop, source, source); } /// @@ -44,7 +45,8 @@ namespace ImageSharp.PixelFormats.PixelBlenders [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Multiply(Vector4 backdrop, Vector4 source, float opacity) { - return Compose(backdrop, source, backdrop * source).Blend(backdrop, opacity); + source.W *= opacity; + return Compose(backdrop, source, backdrop * source); } /// @@ -57,7 +59,8 @@ namespace ImageSharp.PixelFormats.PixelBlenders [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Add(Vector4 backdrop, Vector4 source, float opacity) { - return Compose(backdrop, source, Vector4.Min(Vector4.One, backdrop + source)).Blend(backdrop, opacity); + source.W *= opacity; + return Compose(backdrop, source, Vector4.Min(Vector4.One, backdrop + source)); } /// @@ -70,7 +73,8 @@ namespace ImageSharp.PixelFormats.PixelBlenders [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Substract(Vector4 backdrop, Vector4 source, float opacity) { - return Compose(backdrop, source, Vector4.Max(Vector4.Zero, backdrop - source)).Blend(backdrop, opacity); + source.W *= opacity; + return Compose(backdrop, source, Vector4.Max(Vector4.Zero, backdrop - source)); } /// @@ -83,7 +87,8 @@ namespace ImageSharp.PixelFormats.PixelBlenders [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Screen(Vector4 backdrop, Vector4 source, float opacity) { - return Compose(backdrop, source, Vector4.One - ((Vector4.One - backdrop) * (Vector4.One - source))).Blend(backdrop, opacity); + source.W *= opacity; + return Compose(backdrop, source, Vector4.One - ((Vector4.One - backdrop) * (Vector4.One - source))); } /// @@ -96,7 +101,8 @@ namespace ImageSharp.PixelFormats.PixelBlenders [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Darken(Vector4 backdrop, Vector4 source, float opacity) { - return Compose(backdrop, source, Vector4.Min(backdrop, source)).Blend(backdrop, opacity); + source.W *= opacity; + return Compose(backdrop, source, Vector4.Min(backdrop, source)); } /// @@ -109,7 +115,8 @@ namespace ImageSharp.PixelFormats.PixelBlenders [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Lighten(Vector4 backdrop, Vector4 source, float opacity) { - return Compose(backdrop, source, Vector4.Max(backdrop, source)).Blend(backdrop, opacity); + source.W *= opacity; + return Compose(backdrop, source, Vector4.Max(backdrop, source)); } /// @@ -127,7 +134,7 @@ namespace ImageSharp.PixelFormats.PixelBlenders 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))).Blend(backdrop, opacity); + return Compose(backdrop, source, Vector4.Min(Vector4.One, new Vector4(cr, cg, cb, 0))); } /// @@ -140,11 +147,12 @@ namespace ImageSharp.PixelFormats.PixelBlenders [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))).Blend(backdrop, opacity); + return Compose(backdrop, source, Vector4.Min(Vector4.One, new Vector4(cr, cg, cb, 0))); } /// @@ -183,11 +191,5 @@ namespace ImageSharp.PixelFormats.PixelBlenders return xform; } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vector4 Blend(this Vector4 source, Vector4 backdrop, float opacity) - { - return Vector4.Lerp(backdrop, source, opacity); - } } } \ No newline at end of file