Browse Source

Another files converted

flabbet 2 years ago
parent
commit
f0a7135530
22 changed files with 433 additions and 54 deletions
  1. 6 6
      src/ChunkyImageLib/Operations/EllipseOperation.cs
  2. 1 0
      src/ChunkyImageLib/Surface.cs
  3. 3 2
      src/PixiEditor.ChangeableDocument/Changes/Drawing/FloodFill/FloodFillHelper.cs
  4. 3 3
      src/PixiEditor.ChangeableDocument/Changes/Selection/SelectEllipse_UpdateableChange.cs
  5. 12 11
      src/PixiEditor.ChangeableDocument/Changes/Selection/SelectLasso_UpdateableChange.cs
  6. 13 11
      src/PixiEditor.ChangeableDocument/Changes/Selection/SelectRectangle_UpdateableChange.cs
  7. 9 8
      src/PixiEditor.ChangeableDocument/Changes/Selection/SetSelection_Change.cs
  8. 4 3
      src/PixiEditor.ChangeableDocument/Changes/Selection/TransformSelectionPath_UpdateableChange.cs
  9. 6 5
      src/PixiEditor.ChangeableDocument/Enums/SelectionModeEx.cs
  10. 4 0
      src/PixiEditor.DrawingApi.Core/Bridge/NativeObjectsImpl/IVectorPathImplementation.cs
  11. 3 1
      src/PixiEditor.DrawingApi.Core/Bridge/Operations/ICanvasOperations.cs
  12. 1 0
      src/PixiEditor.DrawingApi.Core/Bridge/Operations/IImageOperations.cs
  13. 15 2
      src/PixiEditor.DrawingApi.Core/Surface/Canvas.cs
  14. 11 0
      src/PixiEditor.DrawingApi.Core/Surface/ClipOperation.cs
  15. 8 1
      src/PixiEditor.DrawingApi.Core/Surface/DrawingSurface.cs
  16. 23 0
      src/PixiEditor.DrawingApi.Core/Surface/ImageData/AlphaType.cs
  17. 8 0
      src/PixiEditor.DrawingApi.Core/Surface/ImageData/ColorSpace.cs
  18. 64 0
      src/PixiEditor.DrawingApi.Core/Surface/ImageData/ColorType.cs
  19. 1 1
      src/PixiEditor.DrawingApi.Core/Surface/ImageData/Image.cs
  20. 198 0
      src/PixiEditor.DrawingApi.Core/Surface/ImageData/ImageInfo.cs
  21. 20 0
      src/PixiEditor.DrawingApi.Core/Surface/Vector/VectorPath.cs
  22. 20 0
      src/PixiEditor.DrawingApi.Core/Surface/Vector/VectorPathOp.cs

+ 6 - 6
src/ChunkyImageLib/Operations/EllipseOperation.cs

@@ -69,24 +69,24 @@ internal class EllipseOperation : IDrawOperation
             if (fillColor.A > 0 || paint.BlendMode != BlendMode.SrcOver)
             {
                 paint.Color = fillColor;
-                surf.Canvas.DrawPoints(PointMode.Lines, ellipseFill, paint);
-                surf.Canvas.DrawRect(ellipseFillRect!, paint);
+                surf.Canvas.DrawPoints(PointMode.Lines, ellipseFill!, paint);
+                surf.Canvas.DrawRect(ellipseFillRect!.Value, paint);
             }
             paint.Color = strokeColor;
-            surf.Canvas.DrawPoints(PointMode.Points, ellipse, paint);
+            surf.Canvas.DrawPoints(PointMode.Points, ellipse!, paint);
         }
         else
         {
             if (fillColor.A > 0 || paint.BlendMode != BlendMode.SrcOver)
             {
                 surf.Canvas.Save();
-                surf.Canvas.ClipPath(innerPath);
+                surf.Canvas.ClipPath(innerPath!);
                 surf.Canvas.DrawColor(fillColor, paint.BlendMode);
                 surf.Canvas.Restore();
             }
             surf.Canvas.Save();
-            surf.Canvas.ClipPath(outerPath);
-            surf.Canvas.ClipPath(innerPath, SKClipOperation.Difference);
+            surf.Canvas.ClipPath(outerPath!);
+            surf.Canvas.ClipPath(innerPath!, ClipOperation.Difference);
             surf.Canvas.DrawColor(strokeColor, paint.BlendMode);
             surf.Canvas.Restore();
         }

+ 1 - 0
src/ChunkyImageLib/Surface.cs

@@ -4,6 +4,7 @@ using ChunkyImageLib.DataHolders;
 using PixiEditor.DrawingApi.Core.ColorsImpl;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.DrawingApi.Core.Surface;
+using PixiEditor.DrawingApi.Core.Surface.ImageData;
 using PixiEditor.PixelE;
 using SkiaSharp;
 

+ 3 - 2
src/PixiEditor.ChangeableDocument/Changes/Drawing/FloodFill/FloodFillHelper.cs

@@ -6,6 +6,7 @@ using ChunkyImageLib;
 using PixiEditor.DrawingApi.Core.ColorsImpl;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.DrawingApi.Core.Surface;
+using PixiEditor.DrawingApi.Core.Surface.ImageData;
 using PixiEditor.DrawingApi.Core.Surface.Vector;
 
 namespace PixiEditor.ChangeableDocument.Changes.Drawing.FloodFill;
@@ -199,8 +200,8 @@ internal static class FloodFillHelper
 
         fixed (byte* arr = array)
         {
-            using DrawingSurface drawingSurface = SKSurface.Create(
-                new SKImageInfo(localBounds.Right, localBounds.Bottom, ColorType.Gray8, AlphaType.Opaque), (IntPtr)arr, chunkSize);
+            using DrawingSurface drawingSurface = DrawingSurface.Create(
+                new ImageInfo(localBounds.Right, localBounds.Bottom, ColorType.Gray8, AlphaType.Opaque), (IntPtr)arr, chunkSize);
             drawingSurface.Canvas.ClipPath(shiftedSelection);
             drawingSurface.Canvas.Clear(new Color(InSelection, InSelection, InSelection));
             drawingSurface.Canvas.Flush();

+ 3 - 3
src/PixiEditor.ChangeableDocument/Changes/Selection/SelectEllipse_UpdateableChange.cs

@@ -9,7 +9,7 @@ internal class SelectEllipse_UpdateableChange : UpdateableChange
 {
     private RectI borders;
     private readonly SelectionMode mode;
-    private SKPath? originalPath;
+    private VectorPath? originalPath;
 
     [GenerateUpdateableChangeActions]
     public SelectEllipse_UpdateableChange(RectI borders, SelectionMode mode)
@@ -40,7 +40,7 @@ internal class SelectEllipse_UpdateableChange : UpdateableChange
         if (mode == SelectionMode.New)
             target.Selection.SelectionPath = new(ellipsePath);
         else
-            target.Selection.SelectionPath = originalPath!.Op(ellipsePath, mode.ToSKPathOp());
+            target.Selection.SelectionPath = originalPath!.Op(ellipsePath, mode.ToVectorPathOp());
         toDispose.Dispose();
 
         return new Selection_ChangeInfo(new VectorPath(target.Selection.SelectionPath));
@@ -60,7 +60,7 @@ internal class SelectEllipse_UpdateableChange : UpdateableChange
 
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     {
-        (var toDispose, target.Selection.SelectionPath) = (target.Selection.SelectionPath, new VectorPath(originalPath));
+        (var toDispose, target.Selection.SelectionPath) = (target.Selection.SelectionPath, new VectorPath(originalPath!));
         toDispose.Dispose();
         return new Selection_ChangeInfo(new VectorPath(target.Selection.SelectionPath));
     }

+ 12 - 11
src/PixiEditor.ChangeableDocument/Changes/Selection/SelectLasso_UpdateableChange.cs

@@ -1,30 +1,31 @@
 using PixiEditor.ChangeableDocument.Enums;
 using PixiEditor.DrawingApi.Core.Numerics;
-using SkiaSharp;
+using PixiEditor.DrawingApi.Core.Surface;
+using PixiEditor.DrawingApi.Core.Surface.Vector;
 
 namespace PixiEditor.ChangeableDocument.Changes.Selection;
 internal class SelectLasso_UpdateableChange : UpdateableChange
 {
-    private SKPath? originalPath;
-    private SKPath path = new() { FillType = SKPathFillType.EvenOdd };
+    private VectorPath? originalPath;
+    private VectorPath path = new() { FillType = PathFillType.EvenOdd };
     private readonly SelectionMode mode;
 
     [GenerateUpdateableChangeActions]
     public SelectLasso_UpdateableChange(VecI point, SelectionMode mode)
     {
-        path.MoveTo(point);
+        path.MoveTo((Point)point);
         this.mode = mode;
     }
 
     [UpdateChangeMethod]
     public void Update(VecI point)
     {
-        path.LineTo(point);
+        path.LineTo((Point)point);
     }
 
     public override OneOf<Success, Error> InitializeAndValidate(Document target)
     {
-        originalPath = new SKPath(target.Selection.SelectionPath);
+        originalPath = new VectorPath(target.Selection.SelectionPath);
         return new Success();
     }
 
@@ -33,17 +34,17 @@ internal class SelectLasso_UpdateableChange : UpdateableChange
         var toDispose = target.Selection.SelectionPath;
         if (mode == SelectionMode.New)
         {
-            var copy = new SKPath(path);
+            var copy = new VectorPath(path);
             copy.Close();
             target.Selection.SelectionPath = copy;
         }
         else
         {
-            target.Selection.SelectionPath = originalPath!.Op(path, mode.ToSKPathOp());
+            target.Selection.SelectionPath = originalPath!.Op(path, mode.ToVectorPathOp());
         }
         toDispose.Dispose();
 
-        return new Selection_ChangeInfo(new SKPath(target.Selection.SelectionPath));
+        return new Selection_ChangeInfo(new VectorPath(target.Selection.SelectionPath));
     }
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     {
@@ -59,9 +60,9 @@ internal class SelectLasso_UpdateableChange : UpdateableChange
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     {
         var toDispose = target.Selection.SelectionPath;
-        target.Selection.SelectionPath = new(originalPath);
+        target.Selection.SelectionPath = new(originalPath!);
         toDispose.Dispose();
-        return new Selection_ChangeInfo(new SKPath(target.Selection.SelectionPath));
+        return new Selection_ChangeInfo(new VectorPath(target.Selection.SelectionPath));
     }
 
     public override void Dispose()

+ 13 - 11
src/PixiEditor.ChangeableDocument/Changes/Selection/SelectRectangle_UpdateableChange.cs

@@ -1,12 +1,14 @@
 using PixiEditor.ChangeableDocument.Enums;
 using PixiEditor.DrawingApi.Core.Numerics;
+using PixiEditor.DrawingApi.Core.Surface;
+using PixiEditor.DrawingApi.Core.Surface.Vector;
 using SkiaSharp;
 
 namespace PixiEditor.ChangeableDocument.Changes.Selection;
 
 internal class SelectRectangle_UpdateableChange : UpdateableChange
 {
-    private SKPath? originalPath;
+    private VectorPath? originalPath;
     private RectI rect;
     private readonly SelectionMode mode;
 
@@ -18,7 +20,7 @@ internal class SelectRectangle_UpdateableChange : UpdateableChange
     }
     public override OneOf<Success, Error> InitializeAndValidate(Document target)
     {
-        originalPath = new SKPath(target.Selection.SelectionPath);
+        originalPath = new VectorPath(target.Selection.SelectionPath);
         return new Success();
     }
 
@@ -30,13 +32,13 @@ internal class SelectRectangle_UpdateableChange : UpdateableChange
 
     private Selection_ChangeInfo CommonApply(Document target)
     {
-        using var rectPath = new SKPath() { FillType = SKPathFillType.EvenOdd };
+        using var rectPath = new VectorPath() { FillType = PathFillType.EvenOdd };
         if (!rect.IsZeroArea)
         {
-            rectPath.MoveTo(rect.TopLeft);
-            rectPath.LineTo(rect.TopRight);
-            rectPath.LineTo(rect.BottomRight);
-            rectPath.LineTo(rect.BottomLeft);
+            rectPath.MoveTo((Point)rect.TopLeft);
+            rectPath.LineTo((Point)rect.TopRight);
+            rectPath.LineTo((Point)rect.BottomRight);
+            rectPath.LineTo((Point)rect.BottomLeft);
             rectPath.Close();
         }
 
@@ -44,10 +46,10 @@ internal class SelectRectangle_UpdateableChange : UpdateableChange
         if (mode == SelectionMode.New)
             target.Selection.SelectionPath = new(rectPath);
         else
-            target.Selection.SelectionPath = originalPath!.Op(rectPath, mode.ToSKPathOp());
+            target.Selection.SelectionPath = originalPath!.Op(rectPath, mode.ToVectorPathOp());
         toDispose.Dispose();
 
-        return new Selection_ChangeInfo(new SKPath(target.Selection.SelectionPath));
+        return new Selection_ChangeInfo(new VectorPath(target.Selection.SelectionPath));
     }
 
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> ApplyTemporarily(Document target)
@@ -64,9 +66,9 @@ internal class SelectRectangle_UpdateableChange : UpdateableChange
 
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     {
-        (var toDispose, target.Selection.SelectionPath) = (target.Selection.SelectionPath, new SKPath(originalPath));
+        (var toDispose, target.Selection.SelectionPath) = (target.Selection.SelectionPath, new VectorPath(originalPath!));
         toDispose.Dispose();
-        return new Selection_ChangeInfo(new SKPath(target.Selection.SelectionPath));
+        return new Selection_ChangeInfo(new VectorPath(target.Selection.SelectionPath));
     }
 
     public override void Dispose()

+ 9 - 8
src/PixiEditor.ChangeableDocument/Changes/Selection/SetSelection_Change.cs

@@ -1,16 +1,17 @@
 using PixiEditor.ChangeableDocument.Changeables.Interfaces;
+using PixiEditor.DrawingApi.Core.Surface.Vector;
 using SkiaSharp;
 
 namespace PixiEditor.ChangeableDocument.Changes.Selection;
 internal class SetSelection_Change : Change
 {
-    private readonly SKPath selection;
-    private SKPath? originalSelection;
+    private readonly VectorPath selection;
+    private VectorPath? originalSelection;
 
     [GenerateMakeChangeAction]
-    public SetSelection_Change(SKPath selection)
+    public SetSelection_Change(VectorPath selection)
     {
-        this.selection = new SKPath(selection) { FillType = SKPathFillType.EvenOdd };
+        this.selection = new VectorPath(selection) { FillType = PathFillType.EvenOdd };
     }
 
     public override OneOf<Success, Error> InitializeAndValidate(Document target)
@@ -21,14 +22,14 @@ internal class SetSelection_Change : Change
 
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     {
-        target.Selection.SelectionPath = new SKPath(selection) { FillType = SKPathFillType.EvenOdd };
+        target.Selection.SelectionPath = new VectorPath(selection) { FillType = PathFillType.EvenOdd };
         ignoreInUndo = false;
-        return new Selection_ChangeInfo(new SKPath(selection) { FillType = SKPathFillType.EvenOdd });
+        return new Selection_ChangeInfo(new VectorPath(selection) { FillType = PathFillType.EvenOdd });
     }
 
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     {
-        target.Selection.SelectionPath = new SKPath(originalSelection) { FillType = SKPathFillType.EvenOdd };
-        return new Selection_ChangeInfo(new SKPath(originalSelection) { FillType = SKPathFillType.EvenOdd });
+        target.Selection.SelectionPath = new VectorPath(originalSelection!) { FillType = PathFillType.EvenOdd };
+        return new Selection_ChangeInfo(new VectorPath(originalSelection!) { FillType = PathFillType.EvenOdd });
     }
 }

+ 4 - 3
src/PixiEditor.ChangeableDocument/Changes/Selection/TransformSelectionPath_UpdateableChange.cs

@@ -1,10 +1,11 @@
 using PixiEditor.DrawingApi.Core.Numerics;
+using PixiEditor.DrawingApi.Core.Surface.Vector;
 using SkiaSharp;
 
 namespace PixiEditor.ChangeableDocument.Changes.Selection;
 internal class TransformSelectionPath_UpdateableChange : UpdateableChange
 {
-    private SKPath? originalPath;
+    private VectorPath? originalPath;
     private RectI originalTightBounds;
     private ShapeCorners newCorners;
 
@@ -43,9 +44,9 @@ internal class TransformSelectionPath_UpdateableChange : UpdateableChange
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     {
         var toDispose = target.Selection.SelectionPath;
-        target.Selection.SelectionPath = new SKPath(originalPath);
+        target.Selection.SelectionPath = new VectorPath(originalPath!);
         toDispose.Dispose();
-        return new Selection_ChangeInfo(new SKPath(target.Selection.SelectionPath));
+        return new Selection_ChangeInfo(new VectorPath(target.Selection.SelectionPath));
     }
 
     public override void Dispose()

+ 6 - 5
src/PixiEditor.ChangeableDocument/Enums/SelectionModeEx.cs

@@ -1,16 +1,17 @@
-using SkiaSharp;
+using PixiEditor.DrawingApi.Core.Surface.Vector;
+using SkiaSharp;
 
 namespace PixiEditor.ChangeableDocument.Enums;
 internal static class SelectionModeEx
 {
-    public static SKPathOp ToSKPathOp(this SelectionMode mode)
+    public static VectorPathOp ToVectorPathOp(this SelectionMode mode)
     {
         return mode switch
         {
             SelectionMode.New => throw new ArgumentException("The New mode has no corresponding operation"),
-            SelectionMode.Add => SKPathOp.Union,
-            SelectionMode.Subtract => SKPathOp.Difference,
-            SelectionMode.Intersect => SKPathOp.Intersect,
+            SelectionMode.Add => VectorPathOp.Union,
+            SelectionMode.Subtract => VectorPathOp.Difference,
+            SelectionMode.Intersect => VectorPathOp.Intersect,
             _ => throw new NotImplementedException(),
         };
     }

+ 4 - 0
src/PixiEditor.DrawingApi.Core/Bridge/NativeObjectsImpl/IVectorPathImplementation.cs

@@ -29,4 +29,8 @@ public interface IVectorPathImplementation
     public void LineTo(VectorPath vectorPath, Point point);
     public void QuadTo(VectorPath vectorPath, Point mid, Point point);
     public void CubicTo(VectorPath vectorPath, Point mid1, Point mid2, Point point);
+    public void ArcTo(VectorPath vectorPath, RectI oval, int startAngle, int sweepAngle, bool forceMoveTo);
+    public void AddOval(VectorPath vectorPath, RectI borders);
+    public VectorPath Op(VectorPath vectorPath, VectorPath ellipsePath, VectorPathOp pathOp);
+    public void Close(VectorPath vectorPath);
 }

+ 3 - 1
src/PixiEditor.DrawingApi.Core/Bridge/Operations/ICanvasOperations.cs

@@ -1,6 +1,7 @@
 using PixiEditor.DrawingApi.Core.ColorsImpl;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.DrawingApi.Core.Surface;
+using PixiEditor.DrawingApi.Core.Surface.ImageData;
 using PixiEditor.DrawingApi.Core.Surface.Vector;
 
 namespace PixiEditor.DrawingApi.Core.Bridge.Operations
@@ -18,7 +19,7 @@ namespace PixiEditor.DrawingApi.Core.Bridge.Operations
         public void DrawPoint(VecI pos, Paint paint);
         public void DrawPoints(PointMode pointMode, Point[] points, Paint paint);
         public void DrawRect(int x, int y, int width, int height, Paint paint);
-        public void ClipPath(VectorPath clipPath);
+        public void ClipPath(VectorPath clipPath, ClipOperation clipOperation, bool antialias);
         public void ClipRect(RectD rect);
         public void Clear();
         public void Clear(Color color);
@@ -26,5 +27,6 @@ namespace PixiEditor.DrawingApi.Core.Bridge.Operations
         public void Flush();
         public void SetMatrix(Matrix3X3 finalMatrix);
         public void RestoreToCount(int count);
+        public void DrawColor(Color color, BlendMode paintBlendMode);
     }
 }

+ 1 - 0
src/PixiEditor.DrawingApi.Core/Bridge/Operations/IImageOperations.cs

@@ -1,4 +1,5 @@
 using PixiEditor.DrawingApi.Core.Surface;
+using PixiEditor.DrawingApi.Core.Surface.ImageData;
 
 namespace PixiEditor.DrawingApi.Core.Bridge.Operations
 {

+ 15 - 2
src/PixiEditor.DrawingApi.Core/Surface/Canvas.cs

@@ -1,6 +1,7 @@
 using PixiEditor.DrawingApi.Core.Bridge;
 using PixiEditor.DrawingApi.Core.ColorsImpl;
 using PixiEditor.DrawingApi.Core.Numerics;
+using PixiEditor.DrawingApi.Core.Surface.ImageData;
 using PixiEditor.DrawingApi.Core.Surface.Vector;
 using SkiaSharp;
 
@@ -82,10 +83,17 @@ namespace PixiEditor.DrawingApi.Core.Surface
         {
             DrawingBackendApi.Current.CanvasOperations.DrawRect(x, y, width, height, paint);
         }
+        
+        public void DrawRect(RectI rect, Paint paint) => DrawRect(rect.X, rect.Y, rect.Width, rect.Height, paint);
+
+        public void ClipPath(VectorPath clipPath) => ClipPath(clipPath, ClipOperation.Intersect);
 
-        public void ClipPath(VectorPath clipPath)
+        public void ClipPath(VectorPath clipPath, ClipOperation clipOperation) =>
+            ClipPath(clipPath, clipOperation, false);
+        
+        public void ClipPath(VectorPath clipPath, ClipOperation clipOperation, bool antialias)
         {
-            DrawingBackendApi.Current.CanvasOperations.ClipPath(clipPath);
+            DrawingBackendApi.Current.CanvasOperations.ClipPath(clipPath, clipOperation, antialias);
         }
 
         public void ClipRect(RectD rect)
@@ -122,5 +130,10 @@ namespace PixiEditor.DrawingApi.Core.Surface
         {
             DrawingBackendApi.Current.CanvasOperations.RestoreToCount(count);
         }
+
+        public void DrawColor(Color color, BlendMode paintBlendMode)
+        {
+            DrawingBackendApi.Current.CanvasOperations.DrawColor(color, paintBlendMode);
+        }
     }
 }

+ 11 - 0
src/PixiEditor.DrawingApi.Core/Surface/ClipOperation.cs

@@ -0,0 +1,11 @@
+namespace PixiEditor.DrawingApi.Core.Surface;
+
+/// <summary>The logical operations that can be performed when combining two regions.</summary>
+public enum ClipOperation
+{
+    /// <summary>Subtract the op region from the first region.</summary>
+    Difference,
+    
+    /// <summary>Intersect the two regions.</summary>
+    Intersect,
+}

+ 8 - 1
src/PixiEditor.DrawingApi.Core/Surface/DrawingSurface.cs

@@ -1,4 +1,6 @@
-using PixiEditor.DrawingApi.Core.Bridge;
+using System;
+using PixiEditor.DrawingApi.Core.Bridge;
+using PixiEditor.DrawingApi.Core.Surface.ImageData;
 
 namespace PixiEditor.DrawingApi.Core.Surface
 {
@@ -19,5 +21,10 @@ namespace PixiEditor.DrawingApi.Core.Surface
         {
             return DrawingBackendApi.Current.ImageOperations.PeekPixels(this);
         }
+
+        public static DrawingSurface Create(ImageInfo imageInfo, IntPtr arr, int chunkSize)
+        {
+            
+        }
     }
 }

+ 23 - 0
src/PixiEditor.DrawingApi.Core/Surface/ImageData/AlphaType.cs

@@ -0,0 +1,23 @@
+namespace PixiEditor.DrawingApi.Core.Surface.ImageData;
+
+/// <summary>Describes how to interpret the alpha component of a pixel.</summary>
+public enum AlphaType
+{
+    /// <summary />
+    Unknown,
+    
+    /// <summary>All pixels are stored as opaque.</summary>
+    Opaque,
+    
+    /// <summary>
+    ///     <para>All pixels have their alpha premultiplied in their color components.</para>
+    ///     <para>This is the natural format for the rendering target pixels.</para>
+    /// </summary>
+    Premul,
+    
+    /// <summary>
+    ///     <para>All pixels have their color components stored without any regard to the alpha. e.g. this is the default configuration for PNG images.</para>
+    ///     <para>This alpha-type is ONLY supported for input images. Rendering cannot generate this on output.</para>
+    /// </summary>
+    Unpremul,
+}

+ 8 - 0
src/PixiEditor.DrawingApi.Core/Surface/ImageData/ColorSpace.cs

@@ -0,0 +1,8 @@
+using SkiaSharp;
+
+namespace PixiEditor.DrawingApi.Core.Surface.ImageData;
+
+public class ColorSpace
+{
+    
+}

+ 64 - 0
src/PixiEditor.DrawingApi.Core/Surface/ImageData/ColorType.cs

@@ -0,0 +1,64 @@
+using SkiaSharp;
+
+namespace PixiEditor.DrawingApi.Core.Surface.ImageData;
+
+/// <summary>Describes how to interpret the components of a pixel.</summary>
+public enum ColorType
+{
+    /// <summary>Unknown encoding.</summary>
+    Unknown,
+    
+    /// <summary>Represents a 8-bit alpha-only color.</summary>
+    Alpha8,
+    
+    /// <summary>Represents an opaque 16-bit color with the format RGB, with the red and blue components being 5 bits and the green component being 6 bits.</summary>
+    Rgb565,
+    
+    /// <summary>Represents a 16-bit color with the format ARGB.</summary>
+    Argb4444,
+    
+    /// <summary>Represents a 32-bit color with the format RGBA.</summary>
+    Rgba8888,
+    
+    /// <summary>Represents an opaque 32-bit color with the format RGB, with 8 bits per color component.</summary>
+    Rgb888x,
+    
+    /// <summary>Represents a 32-bit color with the format BGRA.</summary>
+    Bgra8888,
+    
+    /// <summary>Represents a 32-bit color with the format RGBA, with 10 bits per color component and 2 bits for the alpha component.</summary>
+    Rgba1010102,
+    
+    /// <summary>Represents an opaque 32-bit color with the format RGB, with 10 bits per color component.</summary>
+    Rgb101010x,
+    
+    /// <summary>Represents an opaque 8-bit grayscale color.</summary>
+    Gray8,
+    
+    /// <summary>Represents a floating-point based color with the format RGBA.</summary>
+    RgbaF16,
+    
+    /// <summary>To be added.</summary>
+    RgbaF16Clamped,
+    
+    /// <summary>To be added.</summary>
+    RgbaF32,
+    
+    /// <summary>To be added.</summary>
+    Rg88,
+    
+    /// <summary>To be added.</summary>
+    AlphaF16,
+    
+    /// <summary>To be added.</summary>
+    RgF16,
+    
+    /// <summary>To be added.</summary>
+    Alpha16,
+    
+    /// <summary>To be added.</summary>
+    Rg1616,
+    
+    /// <summary>To be added.</summary>
+    Rgba16161616,
+}

+ 1 - 1
src/PixiEditor.DrawingApi.Core/Surface/Image.cs → src/PixiEditor.DrawingApi.Core/Surface/ImageData/Image.cs

@@ -1,6 +1,6 @@
 using PixiEditor.DrawingApi.Core.Bridge;
 
-namespace PixiEditor.DrawingApi.Core.Surface
+namespace PixiEditor.DrawingApi.Core.Surface.ImageData
 {
     /// <summary>An abstraction for drawing a rectangle of pixels.</summary>
     /// <remarks>

+ 198 - 0
src/PixiEditor.DrawingApi.Core/Surface/ImageData/ImageInfo.cs

@@ -0,0 +1,198 @@
+using PixiEditor.DrawingApi.Core.Numerics;
+using HashCode = System.HashCode;
+
+namespace PixiEditor.DrawingApi.Core.Surface.ImageData;
+
+public struct ImageInfo : System.IEquatable<ImageInfo>
+  {
+    /// <summary>An empty <see cref="ImageInfo" />.</summary>
+    public static readonly ImageInfo Empty;
+    
+    /// <summary>The current 32-bit color for the current platform.</summary>
+    /// <remarks>On Windows, it is typically <see cref="ColorType.Bgra8888" />, and on Unix-based systems (macOS, Linux) it is typically <see cref="ColorType.Rgba8888" />.</remarks>
+    public static readonly ColorType PlatformColorType = SkiaApi.sk_colortype_get_default_8888().FromNative();
+    
+    /// <summary>The number of bits to shift left for the alpha color component.</summary>
+    public static readonly int PlatformColorAlphaShift;
+    
+    /// <summary>The number of bits to shift left for the red color component.</summary>
+    public static readonly int PlatformColorRedShift;
+    
+    /// <summary>The number of bits to shift left for the green color component.</summary>
+    public static readonly int PlatformColorGreenShift;
+    
+    /// <summary>The number of bits to shift left for the blue color component.</summary>
+    public static readonly int PlatformColorBlueShift;
+
+    static unsafe ImageInfo()
+    {
+      fixed (int* a = &ImageInfo.PlatformColorAlphaShift)
+        fixed (int* r = &ImageInfo.PlatformColorRedShift)
+          fixed (int* g = &ImageInfo.PlatformColorGreenShift)
+            fixed (int* b = &ImageInfo.PlatformColorBlueShift)
+              SkiaApi.sk_color_get_bit_shift(a, r, g, b);
+    }
+
+    /// <summary>Gets or sets the width.</summary>
+    /// <value />
+    public int Width { get; set; }
+
+    /// <summary>Gets or sets the height.</summary>
+    /// <value />
+    public int Height { get; set; }
+
+    /// <summary>Gets or sets the color type.</summary>
+    /// <value />
+    public ColorType ColorType { get; set; }
+
+    /// <summary>Gets the transparency type for the image info.</summary>
+    /// <value />
+    public AlphaType AlphaType { get; set; }
+
+    /// <summary>Gets or sets the color space.</summary>
+    /// <value />
+    public ColorSpace ColorSpace { get; set; }
+
+    public ImageInfo(int width, int height)
+    {
+      this.Width = width;
+      this.Height = height;
+      this.ColorType = ImageInfo.PlatformColorType;
+      this.AlphaType = AlphaType.Premul;
+      this.ColorSpace = (ColorSpace) null;
+    }
+
+    public ImageInfo(int width, int height, ColorType colorType)
+    {
+      this.Width = width;
+      this.Height = height;
+      this.ColorType = colorType;
+      this.AlphaType = AlphaType.Premul;
+      this.ColorSpace = (ColorSpace)null;
+    }
+
+    public ImageInfo(int width, int height, ColorType colorType, AlphaType alphaType)
+    {
+      this.Width = width;
+      this.Height = height;
+      this.ColorType = colorType;
+      this.AlphaType = alphaType;
+      this.ColorSpace = (ColorSpace) null;
+    }
+
+    public ImageInfo(
+      int width,
+      int height,
+      ColorType colorType,
+      AlphaType alphaType,
+      ColorSpace colorspace)
+    {
+      this.Width = width;
+      this.Height = height;
+      this.ColorType = colorType;
+      this.AlphaType = alphaType;
+      this.ColorSpace = colorspace;
+    }
+
+    /// <summary>Gets the number of bytes used per pixel.</summary>
+    /// <value />
+    /// <remarks>This is calculated from the <see cref="ImageInfo.ColorType" />. If the color type is <see cref="ColorType.Unknown" />, then the value will be 0.</remarks>
+    public readonly int BytesPerPixel => this.ColorType.GetBytesPerPixel();
+
+    /// <summary>Gets the number of bits used per pixel.</summary>
+    /// <value />
+    /// <remarks>This is equivalent to multiplying the <see cref="ImageInfo.BytesPerPixel" /> by 8 (the number of bits in a byte).</remarks>
+    public readonly int BitsPerPixel => this.BytesPerPixel * 8;
+
+    /// <summary>Gets the total number of bytes needed to store the bitmap data.</summary>
+    /// <value />
+    /// <remarks>This is calculated as: <see cref="P:SkiaSharp.ImageInfo.Width" /> * <see cref="ImageInfo.Height" /> * <see cref="ImageInfo.BytesPerPixel" />.</remarks>
+    public readonly int BytesSize => this.Width * this.Height * this.BytesPerPixel;
+
+    /// <summary>Gets the total number of bytes needed to store the bitmap data as a 64-bit integer.</summary>
+    /// <value />
+    /// <remarks>This is calculated as: <see cref="P:SkiaSharp.ImageInfo.Width" /> * <see cref="ImageInfo.Height" /> * <see cref="ImageInfo.BytesPerPixel" />.</remarks>
+    public readonly long BytesSize64 => (long) this.Width * (long) this.Height * (long) this.BytesPerPixel;
+
+    /// <summary>Gets the number of bytes per row.</summary>
+    /// <value />
+    /// <remarks>This is calculated as: <see cref="P:SkiaSharp.ImageInfo.Width" /> * <see cref="ImageInfo.BytesPerPixel" />.</remarks>
+    public readonly int RowBytes => this.Width * this.BytesPerPixel;
+
+    /// <summary>Gets the number of bytes per row as a 64-bit integer.</summary>
+    /// <value />
+    /// <remarks>This is calculated as: <see cref="ImageInfo.Width" /> * <see cref="ImageInfo.BytesPerPixel" />.</remarks>
+    public readonly long RowBytes64 => (long) this.Width * (long) this.BytesPerPixel;
+
+    /// <summary>Gets a value indicating whether the width or height are less or equal than zero.</summary>
+    /// <value />
+    public readonly bool IsEmpty => this.Width <= 0 || this.Height <= 0;
+
+    /// <summary>Gets a value indicating whether the configured alpha type is opaque.</summary>
+    /// <value />
+    public readonly bool IsOpaque => this.AlphaType == AlphaType.Opaque;
+
+    /// <summary>Gets the current size of the image.</summary>
+    /// <value />
+    public readonly VecI Size => new VecI(this.Width, this.Height);
+
+    /// <summary>Gets a rectangle with the current width and height.</summary>
+    /// <value />
+    public readonly RectI Rect => RectI.Create(this.Width, this.Height);
+
+
+    public readonly ImageInfo WithSize(VecI size) => this.WithSize(size.Width, size.Height);
+
+    /// <param name="width">The width.</param>
+    /// <param name="height">The height.</param>
+    /// <summary>Creates a new <see cref="ImageInfo" /> with the same properties as this <see cref="ImageInfo" />, but with the specified dimensions.</summary>
+    /// <returns>Returns the new <see cref="ImageInfo" />.</returns>
+    public readonly ImageInfo WithSize(int width, int height) => this with
+    {
+      Width = width,
+      Height = height
+    };
+
+    /// <param name="newColorType">The color type.</param>
+    /// <summary>Creates a new <see cref="ImageInfo" /> with the same properties as this <see cref="ImageInfo" />, but with the specified color type.</summary>
+    /// <returns>Returns the new <see cref="ImageInfo" />.</returns>
+    public readonly ImageInfo WithColorType(ColorType newColorType) => this with
+    {
+      ColorType = newColorType
+    };
+
+    /// <param name="newColorSpace">The color space.</param>
+    /// <summary>Creates a new <see cref="ImageInfo" /> with the same properties as this <see cref="ImageInfo" />, but with the specified color space.</summary>
+    /// <returns>Returns the new <see cref="ImageInfo" />.</returns>
+    public readonly ImageInfo WithColorSpace(ColorSpace newColorSpace) => this with
+    {
+      ColorSpace = newColorSpace
+    };
+
+    /// <param name="newAlphaType">The alpha/transparency type.</param>
+    /// <summary>Creates a new <see cref="ImageInfo" /> with the same properties as this <see cref="ImageInfo" />, but with the specified transparency type.</summary>
+    /// <returns>Returns the new <see cref="ImageInfo" />.</returns>
+    public readonly ImageInfo WithAlphaType(AlphaType newAlphaType) => this with
+    {
+      AlphaType = newAlphaType
+    };
+    
+    public readonly bool Equals(ImageInfo obj) => this.ColorSpace == obj.ColorSpace && this.Width == obj.Width && this.Height == obj.Height && this.ColorType == obj.ColorType && this.AlphaType == obj.AlphaType;
+    
+    public override readonly bool Equals(object obj) => obj is ImageInfo ImageInfo && this.Equals(ImageInfo);
+    
+    public static bool operator ==(ImageInfo left, ImageInfo right) => left.Equals(right);
+    
+    public static bool operator !=(ImageInfo left, ImageInfo right) => !left.Equals(right);
+    
+    public override readonly int GetHashCode()
+    {
+      HashCode hashCode = new HashCode();
+      hashCode.Add<ColorSpace>(this.ColorSpace);
+      hashCode.Add<int>(this.Width);
+      hashCode.Add<int>(this.Height);
+      hashCode.Add<ColorType>(this.ColorType);
+      hashCode.Add<AlphaType>(this.AlphaType);
+      return hashCode.ToHashCode();
+    }
+  }

+ 20 - 0
src/PixiEditor.DrawingApi.Core/Surface/Vector/VectorPath.cs

@@ -90,4 +90,24 @@ public class VectorPath : NativeObject
     {
         DrawingBackendApi.Current.PathImplementation.CubicTo(this, mid1, mid2, point);
     }
+
+    public void ArcTo(RectI oval, int startAngle, int sweepAngle, bool forceMoveTo)
+    {
+        DrawingBackendApi.Current.PathImplementation.ArcTo(this, oval, startAngle, sweepAngle, forceMoveTo);
+    }
+
+    public void AddOval(RectI borders)
+    {
+        DrawingBackendApi.Current.PathImplementation.AddOval(this, borders);
+    }
+
+    public VectorPath Op(VectorPath ellipsePath, VectorPathOp pathOp)
+    {
+        return DrawingBackendApi.Current.PathImplementation.Op(this, ellipsePath, pathOp);
+    }
+
+    public void Close()
+    {
+        DrawingBackendApi.Current.PathImplementation.Close(this);
+    }
 }

+ 20 - 0
src/PixiEditor.DrawingApi.Core/Surface/Vector/VectorPathOp.cs

@@ -0,0 +1,20 @@
+namespace PixiEditor.DrawingApi.Core.Surface.Vector;
+
+/// <summary>The logical operations that can be performed when combining two paths using <see cref="VectorPath.Op(VectorPath, VectorPathOp)" />.</summary>
+public enum VectorPathOp
+{
+    /// <summary>Subtract the op path from the current path.</summary>
+    Difference,
+    
+    /// <summary>Intersect the two paths.</summary>
+    Intersect,
+    
+    /// <summary>Union (inclusive-or) the two paths.</summary>
+    Union,
+    
+    /// <summary>Exclusive-or the two paths.</summary>
+    Xor,
+    
+    /// <summary>Subtract the current path from the op path.</summary>
+    ReverseDifference,
+}