Ver Fonte

Implemented compose in drawing backend and added Filter class to ChangeableDocument

CPKreuz há 1 ano atrás
pai
commit
7d2439b590

+ 48 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Filter.cs

@@ -0,0 +1,48 @@
+using System.Diagnostics.Contracts;
+using PixiEditor.DrawingApi.Core.Surface.PaintImpl;
+
+namespace PixiEditor.ChangeableDocument.Changeables.Graph;
+
+public sealed class Filter : IDisposable
+{
+    private Filter(ColorFilter? colorFilter, ImageFilter? imageFilter)
+    {
+        ColorFilter = colorFilter;
+        ImageFilter = imageFilter;
+    }
+    
+    public ColorFilter? ColorFilter { get; }
+    
+    public ImageFilter? ImageFilter { get; }
+
+    [Pure]
+    public Filter Add(ColorFilter? colorFilter, ImageFilter? imageFilter)
+    {
+        ColorFilter? color = ColorFilter;
+        
+        if (colorFilter != null)
+        {
+            color = ColorFilter == null ? colorFilter : ColorFilter.CreateCompose(colorFilter, ColorFilter);
+        }
+
+        ImageFilter? image = ImageFilter;
+        if (imageFilter == null)
+        {
+            image = ImageFilter == null ? imageFilter : ImageFilter.CreateCompose(imageFilter, ImageFilter);
+        }
+
+        return new Filter(color, image);
+    }
+
+    [Pure]
+    public Filter Add(ColorFilter? colorFilter) => Add(colorFilter, null);
+
+    [Pure]
+    public Filter Add(ImageFilter? imageFilter) => Add(null, imageFilter);
+
+    public void Dispose()
+    {
+        ColorFilter?.Dispose();
+        ImageFilter?.Dispose();
+    }
+}

+ 1 - 0
src/PixiEditor.DrawingApi.Core/Bridge/NativeObjectsImpl/IColorFilterImplementation.cs

@@ -9,6 +9,7 @@ public interface IColorFilterImplementation
 {
     public IntPtr CreateBlendMode(Color color, BlendMode blendMode);
     public IntPtr CreateColorMatrix(float[] matrix);
+    public IntPtr CreateCompose(ColorFilter outer, ColorFilter inner);
     public void Dispose(ColorFilter colorFilter);
     public object GetNativeColorFilter(IntPtr objectPointer);
 }

+ 3 - 0
src/PixiEditor.DrawingApi.Core/Bridge/NativeObjectsImpl/IImageFilterImplementation.cs

@@ -1,5 +1,6 @@
 using System;
 using PixiEditor.DrawingApi.Core.Surface;
+using PixiEditor.DrawingApi.Core.Surface.PaintImpl;
 using PixiEditor.Numerics;
 
 namespace PixiEditor.DrawingApi.Core.Bridge.NativeObjectsImpl;
@@ -8,6 +9,8 @@ public interface IImageFilterImplementation
 {
     IntPtr CreateMatrixConvolution(VecI size, ReadOnlySpan<float> kernel, float gain, float bias, VecI kernelOffset, TileMode mode, bool convolveAlpha);
 
+    IntPtr CreateCompose(ImageFilter outer, ImageFilter inner);
+
     object GetNativeImageFilter(IntPtr objPtr);
     
     void DisposeObject(IntPtr objPtr);

+ 12 - 1
src/PixiEditor.DrawingApi.Core/Surface/PaintImpl/ColorFilter.cs

@@ -19,7 +19,18 @@ public class ColorFilter : NativeObject
         return filter;
     }
 
-    /// <param name="matrix">An array of <see cref="F:SkiaSharp.SKColorFilter.ColorMatrixSize" /> elements.</param>
+    /// <param name="outer">The outer (second) filter to apply.</param>
+    /// <param name="inner">The inner (first) filter to apply.</param>
+    /// <summary>Creates a new composition color filter, whose effect is to first apply the inner filter and then apply the outer filter to the result of the inner.</summary>
+    /// <returns>Returns the new <see cref="T:PixiEditor.DrawingApi.Core.Surface.PaintImpl.ColorFilter" />.</returns>
+    public static ColorFilter CreateCompose(ColorFilter outer, ColorFilter inner)
+    {
+        var handle = DrawingBackendApi.Current.ColorFilterImplementation.CreateCompose(outer, inner);
+        ColorFilter filter = new ColorFilter(handle);
+
+        return filter;
+    }
+
     /// <summary>Creates a new color filter that transforms a color by a 4x5 (row-major) matrix.</summary>
     /// <returns>Returns the new <see cref="T:PixiEditor.DrawingApi.Core.Surface.PaintImpl.ColorFilter" />.</returns>
     /// <remarks>The matrix is in row-major order and the translation column is specified in unnormalized, 0...255, space.</remarks>

+ 7 - 0
src/PixiEditor.DrawingApi.Core/Surface/PaintImpl/ImageFilter.cs

@@ -31,6 +31,13 @@ public class ImageFilter : NativeObject
     public static ImageFilter CreateMatrixConvolution(KernelArray kernel, float gain, float bias, VecI kernelOffset, TileMode tileMode, bool convolveAlpha) =>
         CreateMatrixConvolution(new VecI(kernel.Width, kernel.Height), kernel.AsSpan(), gain, bias, kernelOffset, tileMode, convolveAlpha);
 
+    /// <param name="outer">The outer (second) filter to apply.</param>
+    /// <param name="inner">The inner (first) filter to apply.</param>
+    /// <summary>Creates an image filter, whose effect is to first apply the inner filter and then apply the outer filter to the result of the inner.</summary>
+    /// <returns>Returns the new <see cref="T:PixiEditor.DrawingApi.Core.Surface.PaintImpl.ImageFilter" />, or null on error.</returns>
+    public static ImageFilter CreateCompose(ImageFilter outer, ImageFilter inner) =>
+        new(DrawingBackendApi.Current.ImageFilterImplementation.CreateCompose(outer, inner));
+    
     public override object Native => DrawingBackendApi.Current.ImageFilterImplementation.GetNativeImageFilter(ObjectPointer);
     
     public override void Dispose()

+ 11 - 0
src/PixiEditor.DrawingApi.Skia/Implementations/SkiaColorFilterImplementation.cs

@@ -25,6 +25,17 @@ namespace PixiEditor.DrawingApi.Skia.Implementations
             return skColorFilter.Handle;
         }
 
+        public IntPtr CreateCompose(ColorFilter outer, ColorFilter inner)
+        {
+            var skOuter = ManagedInstances[outer.ObjectPointer];
+            var skInner = ManagedInstances[inner.ObjectPointer];
+
+            var skColorFilter = SKColorFilter.CreateCompose(skOuter, skInner);
+            ManagedInstances[skColorFilter.Handle] = skColorFilter;
+
+            return skColorFilter.Handle;
+        }
+
         public void Dispose(ColorFilter colorFilter)
         {
             SKColorFilter skColorFilter = ManagedInstances[colorFilter.ObjectPointer];

+ 11 - 0
src/PixiEditor.DrawingApi.Skia/Implementations/SkiaImageFilterImplementation.cs

@@ -24,6 +24,17 @@ namespace PixiEditor.DrawingApi.Skia.Implementations
             ManagedInstances[skImageFilter.Handle] = skImageFilter;
             return skImageFilter.Handle;
         }
+        
+        public IntPtr CreateCompose(ImageFilter outer, ImageFilter inner)
+        {
+            var skOuter = ManagedInstances[outer.ObjectPointer];
+            var skInner = ManagedInstances[inner.ObjectPointer];
+
+            var compose = SKImageFilter.CreateCompose(skOuter, skInner);
+            ManagedInstances[compose.Handle] = compose;
+
+            return compose.Handle;
+        }
 
         public object GetNativeImageFilter(IntPtr objPtr) => ManagedInstances[objPtr];
     }