Browse Source

I hope I merged correctly

CPKreuz 3 years ago
parent
commit
c4ed027301
53 changed files with 645 additions and 427 deletions
  1. 27 0
      PixiEditor/Helpers/Converters/DockingManagerActiveContentConverter.cs
  2. 1 5
      PixiEditor/Helpers/Converters/FinalIsVisibleToVisiblityConverter.cs
  3. 6 6
      PixiEditor/Helpers/Converters/IndexOfConverter.cs
  4. 25 6
      PixiEditor/Helpers/Converters/LayersToStructuredLayersConverter.cs
  5. 25 0
      PixiEditor/Helpers/Converters/ViewboxInverseTransformConverter.cs
  6. 31 0
      PixiEditor/Helpers/Extensions/Int32RectEx.cs
  7. 0 25
      PixiEditor/Helpers/Extensions/Int32RectHelpers.cs
  8. 20 7
      PixiEditor/Models/Controllers/BitmapManager.cs
  9. 24 2
      PixiEditor/Models/Controllers/LayerStackRenderer.cs
  10. 9 3
      PixiEditor/Models/Controllers/MouseMovementController.cs
  11. 4 1
      PixiEditor/Models/Controllers/SingleLayerRenderer.cs
  12. 39 0
      PixiEditor/Models/Controllers/SurfaceRenderer.cs
  13. 3 0
      PixiEditor/Models/DataHolders/Document/Document.Constructors.cs
  14. 2 24
      PixiEditor/Models/DataHolders/Document/Document.Layers.cs
  15. 2 2
      PixiEditor/Models/DataHolders/Document/Document.Operations.cs
  16. 11 11
      PixiEditor/Models/DataHolders/Document/Document.cs
  17. 1 1
      PixiEditor/Models/DataHolders/Selection.cs
  18. 1 1
      PixiEditor/Models/IO/Exporter.cs
  19. 5 14
      PixiEditor/Models/IO/Importer.cs
  20. 12 13
      PixiEditor/Models/Layers/Layer.cs
  21. 30 5
      PixiEditor/Models/Layers/Utils/LayerStructureUtils.cs
  22. 4 5
      PixiEditor/Models/Position/CoordinatesCalculator.cs
  23. 3 5
      PixiEditor/Models/Tools/Tool.cs
  24. 8 6
      PixiEditor/Models/Tools/Tools/ColorPickerTool.cs
  25. 5 5
      PixiEditor/Models/Undo/StorageBasedChange.cs
  26. 10 5
      PixiEditor/ViewModels/SubViewModels/Main/IoViewModel.cs
  27. 2 1
      PixiEditor/Views/MainWindow.xaml
  28. 5 6
      PixiEditor/Views/UserControls/DrawingViewPort.xaml
  29. 1 1
      PixiEditor/Views/UserControls/Layers/LayerGroupControl.xaml.cs
  30. 4 2
      PixiEditor/Views/UserControls/Layers/LayerItem.xaml
  31. 16 17
      PixiEditor/Views/UserControls/Layers/LayerItem.xaml.cs
  32. 1 1
      PixiEditor/Views/UserControls/Layers/LayerStructureItemContainer.xaml
  33. 12 0
      PixiEditor/Views/UserControls/PlainLayerView.xaml
  34. 105 0
      PixiEditor/Views/UserControls/PlainLayerView.xaml.cs
  35. 13 30
      PixiEditor/Views/UserControls/PreviewWindow.xaml
  36. 7 17
      PixiEditorTests/ModelsTests/ColorsTests/ExtendedColorTests.cs
  37. 9 10
      PixiEditorTests/ModelsTests/ControllersTests/BitmapManagerTests.cs
  38. 7 8
      PixiEditorTests/ModelsTests/ControllersTests/BitmapOperationsUtilityTests.cs
  39. 10 10
      PixiEditorTests/ModelsTests/ControllersTests/ClipboardControllerTests.cs
  40. 10 11
      PixiEditorTests/ModelsTests/ControllersTests/PixelChangesControllerTests.cs
  41. 11 13
      PixiEditorTests/ModelsTests/DataHoldersTests/BitmapPixelChangesTests.cs
  42. 13 14
      PixiEditorTests/ModelsTests/DataHoldersTests/DocumentTests.cs
  43. 15 15
      PixiEditorTests/ModelsTests/DataHoldersTests/LayerStructureTests.cs
  44. 6 5
      PixiEditorTests/ModelsTests/DataHoldersTests/SelectionTests.cs
  45. 17 4
      PixiEditorTests/ModelsTests/DataHoldersTests/SurfaceTests.cs
  46. 7 8
      PixiEditorTests/ModelsTests/IO/ExporterTests.cs
  47. 2 5
      PixiEditorTests/ModelsTests/IO/ImporterTests.cs
  48. 22 45
      PixiEditorTests/ModelsTests/ImageManipulationTests/BitmapUtilsTests.cs
  49. 13 15
      PixiEditorTests/ModelsTests/LayersTests/LayerTests.cs
  50. 5 6
      PixiEditorTests/ModelsTests/ToolsTests/BrightnessToolTests.cs
  51. 5 5
      PixiEditorTests/ModelsTests/ToolsTests/PenToolTests.cs
  52. 10 16
      PixiEditorTests/ModelsTests/UndoTests/StorageBasedChangeTests.cs
  53. 9 10
      PixiEditorTests/ViewModelsTests/ViewModelMainTests.cs

+ 27 - 0
PixiEditor/Helpers/Converters/DockingManagerActiveContentConverter.cs

@@ -0,0 +1,27 @@
+using PixiEditor.Models.DataHolders;
+using System;
+using System.Globalization;
+using System.Windows;
+using System.Windows.Data;
+
+namespace PixiEditor.Helpers.Converters
+{
+    class DockingManagerActiveContentConverter : IValueConverter
+    {
+        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+        {
+            if (value == null)
+                return DependencyProperty.UnsetValue;
+            if (value is Document document)
+                return document;
+            return DependencyProperty.UnsetValue;
+        }
+
+        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+        {
+            if (value is Document document)
+                return document;
+            return DependencyProperty.UnsetValue;
+        }
+    }
+}

+ 1 - 5
PixiEditor/Helpers/Converters/FinalIsVisibleToVisiblityConverter.cs

@@ -1,11 +1,7 @@
 using PixiEditor.Models.Layers;
 using PixiEditor.ViewModels;
 using System;
-using System.Collections.Generic;
 using System.Globalization;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 using System.Windows;
 using System.Windows.Data;
 using System.Windows.Markup;
@@ -44,4 +40,4 @@ namespace PixiEditor.Helpers.Converters
             throw new NotImplementedException();
         }
     }
-}
+}

+ 6 - 6
PixiEditor/Helpers/Converters/IndexOfConverter.cs

@@ -1,9 +1,8 @@
-using System;
+using PixiEditor.Models.Layers;
+using PixiEditor.ViewModels;
+using System;
 using System.Globalization;
-using System.Linq;
 using System.Windows.Data;
-using PixiEditor.Models.Layers;
-using PixiEditor.ViewModels;
 
 namespace PixiEditor.Helpers.Converters
 {
@@ -13,7 +12,8 @@ namespace PixiEditor.Helpers.Converters
         {
             if (value is Layer layer && ViewModelMain.Current.BitmapManager.ActiveDocument != null)
             {
-                return ViewModelMain.Current.BitmapManager.ActiveDocument.Layers.IndexOf(layer);
+                int index = ViewModelMain.Current.BitmapManager.ActiveDocument.Layers.IndexOf(layer);
+                return index;
             }
 
             return Binding.DoNothing;
@@ -24,4 +24,4 @@ namespace PixiEditor.Helpers.Converters
             throw new NotImplementedException();
         }
     }
-}
+}

+ 25 - 6
PixiEditor/Helpers/Converters/LayersToStructuredLayersConverter.cs

@@ -4,6 +4,7 @@ using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.Globalization;
 using System.Linq;
+using System.Windows;
 using System.Windows.Data;
 
 namespace PixiEditor.Helpers.Converters
@@ -12,7 +13,8 @@ namespace PixiEditor.Helpers.Converters
     public class LayersToStructuredLayersConverter : IMultiValueConverter
     {
         private static StructuredLayerTree cachedTree;
-        private List<Guid> lastLayers = new List<Guid>();
+        private List<Guid> lastLayerGuids = new List<Guid>();
+        private IList<Layer> lastLayers = new List<Layer>();
         private ObservableCollection<GuidStructureItem> lastStructure = new ObservableCollection<GuidStructureItem>();
 
         public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
@@ -24,18 +26,21 @@ namespace PixiEditor.Helpers.Converters
                     cachedTree = new StructuredLayerTree(layers, structure);
                 }
 
-                if (TryFindStructureDifferences(structure) || lastLayers.Count != layers.Count || LayerOrderIsDifferent(layers))
+                if (TryFindStructureDifferences(structure) ||
+                    lastLayerGuids.Count != layers.Count ||
+                    LayerOrderIsDifferent(layers) ||
+                    LayersAreDifferentObjects(layers, lastLayers))
                 {
                     cachedTree = new StructuredLayerTree(layers, structure);
-
-                    lastLayers = layers.Select(x => x.LayerGuid).ToList();
+                    lastLayers = layers;
+                    lastLayerGuids = layers.Select(x => x.LayerGuid).ToList();
                     lastStructure = structure.CloneGroups();
                 }
 
                 return cachedTree.RootDirectoryItems;
             }
 
-            return new StructuredLayerTree(null, null);
+            return DependencyProperty.UnsetValue;
         }
         public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
         {
@@ -44,7 +49,21 @@ namespace PixiEditor.Helpers.Converters
         private bool LayerOrderIsDifferent(IList<Layer> layers)
         {
             var guids = layers.Select(x => x.LayerGuid).ToArray();
-            return !guids.SequenceEqual(lastLayers);
+            return !guids.SequenceEqual(lastLayerGuids);
+        }
+
+        /// <summary>
+        /// This should trigger if you open and close the same files twice.
+        /// Even though the layers are technically the same, having two different objects screws things up down the line.
+        /// </summary>
+        private bool LayersAreDifferentObjects(IList<Layer> layers, IList<Layer> lastLayers)
+        {
+            for (int i = 0; i < layers.Count; i++)
+            {
+                if (layers[i] != lastLayers[i])
+                    return true;
+            }
+            return false;
         }
         private bool TryFindStructureDifferences(LayerStructure structure)
         {

+ 25 - 0
PixiEditor/Helpers/Converters/ViewboxInverseTransformConverter.cs

@@ -0,0 +1,25 @@
+using System;
+using System.Globalization;
+using System.Windows;
+using System.Windows.Data;
+using System.Windows.Media;
+
+namespace PixiEditor.Helpers.Converters
+{
+    class ViewboxInverseTransformConverter : IMultiValueConverter
+    {
+        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
+        {
+            var transform = ((ContainerVisual)VisualTreeHelper.GetChild((DependencyObject)values[0], 0)).Transform;
+            if (transform == null)
+                return DependencyProperty.UnsetValue;
+            return transform.Inverse;
+        }
+
+
+        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
+        {
+            throw new NotImplementedException();
+        }
+    }
+}

+ 31 - 0
PixiEditor/Helpers/Extensions/Int32RectEx.cs

@@ -0,0 +1,31 @@
+using System;
+using System.Windows;
+
+namespace PixiEditor.Helpers.Extensions
+{
+    static class Int32RectEx
+    {
+        public static Int32Rect Intersect(this Int32Rect rect, Int32Rect other)
+        {
+            int rectX2 = rect.X + rect.Width;
+            int rectY2 = rect.Y + rect.Height;
+
+            int otherX2 = other.X + other.Width;
+            int otherY2 = other.Y + other.Height;
+
+            int maxX1 = Math.Max(rect.X, other.X);
+            int maxY1 = Math.Max(rect.Y, other.Y);
+
+            int minX2 = Math.Min(rectX2, otherX2);
+            int minY2 = Math.Min(rectY2, otherY2);
+
+            int width = minX2 - maxX1;
+            int height = minY2 - maxY1;
+
+            if (width <= 0 || height <= 0)
+                return Int32Rect.Empty;
+
+            return new Int32Rect(maxX1, maxY1, width, height);
+        }
+    }
+}

+ 0 - 25
PixiEditor/Helpers/Extensions/Int32RectHelpers.cs

@@ -1,25 +0,0 @@
-using System.Windows;
-
-namespace PixiEditor.Helpers.Extensions
-{
-    public static class Int32RectHelpers
-    {
-        public static Int32Rect Min(this Int32Rect rect, Int32Rect other)
-        {
-            int width = rect.Width;
-            int height = rect.Height;
-
-            if (width + rect.X > other.Width + other.X)
-            {
-                width = other.Width;
-            }
-
-            if (height + rect.Y > other.Height + other.Y)
-            {
-                height = other.Height;
-            }
-
-            return new Int32Rect(rect.X, rect.Y, width, height);
-        }
-    }
-}

+ 20 - 7
PixiEditor/Models/Controllers/BitmapManager.cs

@@ -32,9 +32,10 @@ namespace PixiEditor.Models.Controllers
             MouseController.StoppedRecordingChanges += MouseController_StoppedRecordingChanges;
             MouseController.OnMouseDown += MouseController_OnMouseDown;
             MouseController.OnMouseUp += MouseController_OnMouseUp;
+            MouseController.OnMouseDownCoordinates += MouseController_OnMouseDownCoordinates;
             BitmapOperations = new BitmapOperationsUtility(this);
             ReadonlyToolUtility = new ReadonlyToolUtility();
-        }
+        }
 
         public event EventHandler<DocumentChangedEventArgs> DocumentChanged;
 
@@ -132,7 +133,9 @@ namespace PixiEditor.Models.Controllers
                 }
                 else if (SelectedTool is ReadonlyTool readonlyTool)
                 {
-                    ReadonlyToolUtility.ExecuteTool(MouseController.LastMouseMoveCoordinates, readonlyTool);
+                    ReadonlyToolUtility.ExecuteTool(
+                        MouseController.LastMouseMoveCoordinates,
+                        readonlyTool);
                 }
                 else
                 {
@@ -164,11 +167,7 @@ namespace PixiEditor.Models.Controllers
         private void Controller_MousePositionChanged(object sender, MouseMovementEventArgs e)
         {
             SelectedTool.OnMouseMove(new MouseEventArgs(Mouse.PrimaryDevice, (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds()));
-            if (Mouse.LeftButton == MouseButtonState.Pressed && !IsDraggingViewport() && ActiveDocument != null)
-            {
-                ExecuteTool(e.NewPosition, MouseController.ClickedOnCanvas);
-            }
-            else if (Mouse.LeftButton == MouseButtonState.Released)
+            if (!MaybeExecuteTool(e.NewPosition) && Mouse.LeftButton == MouseButtonState.Released)
             {
                 HighlightPixels(e.NewPosition);
             }
@@ -183,6 +182,20 @@ namespace PixiEditor.Models.Controllers
         {
             SelectedTool.OnMouseUp(e);
         }
+        private void MouseController_OnMouseDownCoordinates(object sender, MouseMovementEventArgs e)
+        {
+            MaybeExecuteTool(e.NewPosition);
+        }
+
+        private bool MaybeExecuteTool(Coordinates newPosition)
+        {
+            if (Mouse.LeftButton == MouseButtonState.Pressed && !IsDraggingViewport() && ActiveDocument != null)
+            {
+                ExecuteTool(newPosition, MouseController.ClickedOnCanvas);
+                return true;
+            }
+            return false;
+        }
 
         private bool IsDraggingViewport()
         {

+ 24 - 2
PixiEditor/Models/Controllers/LayerStackRenderer.cs

@@ -40,6 +40,7 @@ namespace PixiEditor.Models.Controllers
             this.layers = layers;
             this.structure = structure;
             layers.CollectionChanged += OnLayersChanged;
+            SubscribeToAllLayers(layers);
             Resize(width, height);
         }
 
@@ -57,7 +58,9 @@ namespace PixiEditor.Models.Controllers
         public void SetNewLayersCollection(ObservableCollection<Layer> layers)
         {
             layers.CollectionChanged -= OnLayersChanged;
+            UnsubscribeFromAllLayers(this.layers);
             this.layers = layers;
+            SubscribeToAllLayers(layers);
             layers.CollectionChanged += OnLayersChanged;
             Update(new Int32Rect(0, 0, finalSurface.Width, finalSurface.Height));
         }
@@ -70,12 +73,28 @@ namespace PixiEditor.Models.Controllers
             layers.CollectionChanged -= OnLayersChanged;
         }
 
+        private void SubscribeToAllLayers(ObservableCollection<Layer> layers)
+        {
+            foreach (var layer in layers)
+            {
+                layer.LayerBitmapChanged += OnLayerBitmapChanged;
+            }
+        }
+
+        private void UnsubscribeFromAllLayers(ObservableCollection<Layer> layers)
+        {
+            foreach (var layer in layers)
+            {
+                layer.LayerBitmapChanged -= OnLayerBitmapChanged;
+            }
+        }
+
         private void Update(Int32Rect dirtyRectangle)
         {
             finalSurface.SkiaSurface.Canvas.Clear();
             foreach (var layer in layers)
             {
-                if (!layer.IsVisible)
+                if (!LayerStructureUtils.GetFinalLayerIsVisible(layer, structure))
                     continue;
                 BlendingPaint.Color = new SKColor(255, 255, 255, (byte)(LayerStructureUtils.GetFinalLayerOpacity(layer, structure) * 255));
                 layer.LayerBitmap.SkiaSurface.Draw(
@@ -86,7 +105,10 @@ namespace PixiEditor.Models.Controllers
             }
             finalBitmap.Lock();
             finalSurface.SkiaSurface.Draw(backingSurface.Canvas, 0, 0, Surface.ReplacingPaint);
-            finalBitmap.AddDirtyRect(dirtyRectangle.Min(new Int32Rect(0, 0, finalBitmap.PixelWidth, finalBitmap.PixelHeight)));
+
+            dirtyRectangle = dirtyRectangle.Intersect(new Int32Rect(0, 0, finalBitmap.PixelWidth, finalBitmap.PixelHeight));
+
+            finalBitmap.AddDirtyRect(dirtyRectangle);
             finalBitmap.Unlock();
         }
 

+ 9 - 3
PixiEditor/Models/Controllers/MouseMovementController.cs

@@ -1,7 +1,7 @@
-using System;
+using PixiEditor.Models.Position;
+using System;
 using System.Collections.Generic;
 using System.Windows.Input;
-using PixiEditor.Models.Position;
 
 namespace PixiEditor.Models.Controllers
 {
@@ -10,6 +10,7 @@ namespace PixiEditor.Models.Controllers
         public event EventHandler StartedRecordingChanges;
 
         public event EventHandler<MouseEventArgs> OnMouseDown;
+        public event EventHandler<MouseMovementEventArgs> OnMouseDownCoordinates;
 
         public event EventHandler<MouseEventArgs> OnMouseUp;
 
@@ -62,6 +63,11 @@ namespace PixiEditor.Models.Controllers
             OnMouseDown?.Invoke(this, args);
         }
 
+        public void MouseDownCoordinates(Coordinates mouseCoordinates)
+        {
+            OnMouseDownCoordinates?.Invoke(this, new MouseMovementEventArgs(mouseCoordinates));
+        }
+
         /// <summary>
         /// Plain mouse up, does not affect mouse recordings.
         /// </summary>
@@ -80,4 +86,4 @@ namespace PixiEditor.Models.Controllers
             }
         }
     }
-}
+}

+ 4 - 1
PixiEditor/Models/Controllers/SingleLayerRenderer.cs

@@ -1,4 +1,5 @@
-using PixiEditor.Models.Layers;
+using PixiEditor.Helpers.Extensions;
+using PixiEditor.Models.Layers;
 using SkiaSharp;
 using System;
 using System.ComponentModel;
@@ -63,6 +64,8 @@ namespace PixiEditor.Models.Controllers
                     layer.OffsetY,
                     BlendingPaint);
             }
+            dirtyRectangle = dirtyRectangle.Intersect(new Int32Rect(0, 0, finalBitmap.PixelWidth, finalBitmap.PixelHeight));
+
             finalBitmap.AddDirtyRect(dirtyRectangle);
             finalBitmap.Unlock();
         }

+ 39 - 0
PixiEditor/Models/Controllers/SurfaceRenderer.cs

@@ -0,0 +1,39 @@
+using PixiEditor.Models.DataHolders;
+using SkiaSharp;
+using System;
+using System.Windows;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+
+namespace PixiEditor.Models.Controllers
+{
+    class SurfaceRenderer : IDisposable
+    {
+        public SKSurface BackingSurface { get; private set; }
+        public WriteableBitmap FinalBitmap { get; private set; }
+        private SKPaint BlendingPaint { get; } = new SKPaint() { BlendMode = SKBlendMode.SrcOver };
+        public SurfaceRenderer(int width, int height)
+        {
+            FinalBitmap = new WriteableBitmap(width, height, 96, 96, PixelFormats.Pbgra32, null);
+            var imageInfo = new SKImageInfo(width, height, SKColorType.Bgra8888, SKAlphaType.Premul, SKColorSpace.CreateSrgb());
+            BackingSurface = SKSurface.Create(imageInfo, FinalBitmap.BackBuffer, FinalBitmap.BackBufferStride);
+        }
+
+        public void Dispose()
+        {
+            BackingSurface.Dispose();
+            BlendingPaint.Dispose();
+        }
+
+        public void Draw(Surface otherSurface, byte opacity)
+        {
+            BackingSurface.Canvas.Clear();
+            FinalBitmap.Lock();
+            BlendingPaint.Color = new SKColor(255, 255, 255, opacity);
+            //otherSurface.SkiaSurface.Draw(BackingSurface.Canvas, 0, 0, BlendingPaint);
+            BackingSurface.Canvas.DrawImage(otherSurface.SkiaSurface.Snapshot(), new SKRect(0, 0, FinalBitmap.PixelWidth, FinalBitmap.PixelHeight));
+            FinalBitmap.AddDirtyRect(new Int32Rect(0, 0, FinalBitmap.PixelWidth, FinalBitmap.PixelHeight));
+            FinalBitmap.Unlock();
+        }
+    }
+}

+ 3 - 0
PixiEditor/Models/DataHolders/Document/Document.Constructors.cs

@@ -1,6 +1,7 @@
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.Layers;
 using PixiEditor.ViewModels;
+using System;
 using System.Linq;
 
 namespace PixiEditor.Models.DataHolders
@@ -10,6 +11,8 @@ namespace PixiEditor.Models.DataHolders
         public Document(int width, int height)
             : this()
         {
+            if (width <= 0 || height <= 0)
+                throw new ArgumentException("Document dimensions must be greater than 0");
             Width = width;
             Height = height;
             Renderer = new LayerStackRenderer(layers, layerStructure, Width, Height);

+ 2 - 24
PixiEditor/Models/DataHolders/Document/Document.Layers.cs

@@ -2,6 +2,7 @@
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.Enums;
 using PixiEditor.Models.Layers;
+using PixiEditor.Models.Layers.Utils;
 using PixiEditor.Models.Position;
 using PixiEditor.Models.Undo;
 using SkiaSharp;
@@ -120,30 +121,7 @@ namespace PixiEditor.Models.DataHolders
         /// </summary>
         /// <param name="layer">Layer to check.</param>
         /// <returns>True if is visible, false if at least parent is not visible or layer itself is invisible.</returns>
-        public bool GetFinalLayerIsVisible(Layer layer)
-        {
-            if (!layer.IsVisible)
-            {
-                return false;
-            }
-
-            var group = LayerStructure.GetGroupByLayer(layer.LayerGuid);
-            bool atLeastOneParentIsInvisible = false;
-            GuidStructureItem groupToCheck = group;
-            while (groupToCheck != null)
-            {
-                if (!groupToCheck.IsVisible)
-                {
-                    atLeastOneParentIsInvisible = true;
-                    break;
-                }
-
-                groupToCheck = groupToCheck.Parent;
-            }
-
-            return !atLeastOneParentIsInvisible;
-        }
-
+        public bool GetFinalLayerIsVisible(Layer layer) => LayerStructureUtils.GetFinalLayerIsVisible(layer, LayerStructure);
         public void UpdateLayersColor()
         {
             foreach (var layer in Layers)

+ 2 - 2
PixiEditor/Models/DataHolders/Document/Document.Operations.cs

@@ -112,8 +112,8 @@ namespace PixiEditor.Models.DataHolders
             {
                 float widthRatio = (float)newWidth / Width;
                 float heightRatio = (float)newHeight / Height;
-                int layerWidth = (int)(Layers[i].Width * widthRatio);
-                int layerHeight = (int)(Layers[i].Height * heightRatio);
+                int layerWidth = Math.Max(1, (int)(Layers[i].Width * widthRatio));
+                int layerHeight = Math.Max(1, (int)(Layers[i].Height * heightRatio));
 
                 Layers[i].Resize(layerWidth, layerHeight, newWidth, newHeight);
                 Layers[i].Offset = new Thickness(Math.Floor(Layers[i].OffsetX * widthRatio), Math.Floor(Layers[i].OffsetY * heightRatio), 0, 0);

+ 11 - 11
PixiEditor/Models/DataHolders/Document/Document.cs

@@ -2,6 +2,7 @@
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.Enums;
 using PixiEditor.Models.Layers;
+using PixiEditor.Models.Layers.Utils;
 using PixiEditor.Models.Position;
 using PixiEditor.Models.Undo;
 using PixiEditor.ViewModels;
@@ -150,7 +151,7 @@ namespace PixiEditor.Models.DataHolders
         /// </summary>
         public void CenterContent()
         {
-            var layersToCenter = Layers.Where(x => x.IsActive && GetFinalLayerIsVisible(x));
+            var layersToCenter = Layers.Where(x => x.IsActive && LayerStructureUtils.GetFinalLayerIsVisible(x, LayerStructure));
             if (!layersToCenter.Any())
             {
                 return;
@@ -187,7 +188,7 @@ namespace PixiEditor.Models.DataHolders
         private void SetAsActiveOnClick(object obj)
         {
             XamlAccesibleViewModel.BitmapManager.MouseController.StopRecordingMouseMovementChanges();
-            XamlAccesibleViewModel.BitmapManager.MouseController.StartRecordingMouseMovementChanges(true);
+            //XamlAccesibleViewModel.BitmapManager.MouseController.StartRecordingMouseMovementChanges(true);
             if (XamlAccesibleViewModel.BitmapManager.ActiveDocument != this)
             {
                 XamlAccesibleViewModel.BitmapManager.ActiveDocument = this;
@@ -203,12 +204,12 @@ namespace PixiEditor.Models.DataHolders
         {
             if (anchor.HasFlag(AnchorPoint.Center))
             {
-                return Math.Abs((destWidth / 2) - (srcWidth / 2));
+                return (destWidth / 2) - (srcWidth / 2);
             }
 
             if (anchor.HasFlag(AnchorPoint.Right))
             {
-                return Math.Abs(destWidth - srcWidth);
+                return destWidth - srcWidth;
             }
 
             return 0;
@@ -218,12 +219,12 @@ namespace PixiEditor.Models.DataHolders
         {
             if (anchor.HasFlag(AnchorPoint.Middle))
             {
-                return Math.Abs((destHeight / 2) - (srcHeight / 2));
+                return (destHeight / 2) - (srcHeight / 2);
             }
 
             if (anchor.HasFlag(AnchorPoint.Bottom))
             {
-                return Math.Abs(destHeight - srcHeight);
+                return destHeight - srcHeight;
             }
 
             return 0;
@@ -236,11 +237,10 @@ namespace PixiEditor.Models.DataHolders
                 throw new ArgumentException("Not enough layers");
             }
 
-            Layer firstLayer = layers.First();
-            int smallestX = firstLayer.OffsetX;
-            int smallestY = firstLayer.OffsetY;
-            int biggestX = smallestX + firstLayer.Width;
-            int biggestY = smallestY + firstLayer.Height;
+            int smallestX = int.MaxValue;
+            int smallestY = int.MaxValue;
+            int biggestX = int.MinValue;
+            int biggestY = int.MinValue;
 
             foreach (Layer layer in layers)
             {

+ 1 - 1
PixiEditor/Models/DataHolders/Selection.cs

@@ -31,7 +31,7 @@ namespace PixiEditor.Models.DataHolders
             set
             {
                 selectionLayer = value;
-                RaisePropertyChanged("SelectionLayer");
+                RaisePropertyChanged(nameof(SelectionLayer));
             }
         }
 

+ 1 - 1
PixiEditor/Models/IO/Exporter.cs

@@ -100,7 +100,7 @@ namespace PixiEditor.Models.IO
         /// <param name="exportWidth">File width.</param>
         /// <param name="exportHeight">File height.</param>
         /// <param name="bitmap">Bitmap to save.</param>
-        private static void SaveAsPng(string savePath, int exportWidth, int exportHeight, WriteableBitmap bitmap)
+        public static void SaveAsPng(string savePath, int exportWidth, int exportHeight, WriteableBitmap bitmap)
         {
             try
             {

+ 5 - 14
PixiEditor/Models/IO/Importer.cs

@@ -40,21 +40,12 @@ namespace PixiEditor.Models.IO
         /// <param name="path">Path of image.</param>
         public static Surface ImportSurface(string path)
         {
-            try
-            {
-                using var image = SKImage.FromEncodedData(path);
-                Surface surface = new Surface(image.Width, image.Height);
-                surface.SkiaSurface.Canvas.DrawImage(image, new SKPoint(0, 0));
-                return surface;
-            }
-            catch (NotSupportedException)
-            {
+            using var image = SKImage.FromEncodedData(path);
+            if (image == null)
                 throw new CorruptedFileException();
-            }
-            catch (FileFormatException)
-            {
-                throw new CorruptedFileException();
-            }
+            Surface surface = new Surface(image.Width, image.Height);
+            surface.SkiaSurface.Canvas.DrawImage(image, new SKPoint(0, 0));
+            return surface;
         }
 
         public static WriteableBitmap ImportWriteableBitmap(string path)

+ 12 - 13
PixiEditor/Models/Layers/Layer.cs

@@ -14,7 +14,6 @@ namespace PixiEditor.Models.Layers
     [DebuggerDisplay("'{name,nq}' {width}x{height}")]
     public class Layer : BasicLayer
     {
-        private const int SizeOfArgb = 4;
         private bool clipRequested;
 
         private bool isActive;
@@ -95,12 +94,11 @@ namespace PixiEditor.Models.Layers
             get => isVisible;
             set
             {
-                if (SetProperty(ref isVisible, value))
-                {
-                    RaisePropertyChanged(nameof(IsVisibleUndoTriggerable));
-                    InvokeLayerBitmapChange();
-                    ViewModelMain.Current.ToolsSubViewModel.TriggerCacheOutdated();
-                }
+                isVisible = value;
+                RaisePropertyChanged(nameof(IsVisibleUndoTriggerable));
+                RaisePropertyChanged(nameof(IsVisible));
+                ViewModelMain.Current?.ToolsSubViewModel?.TriggerCacheOutdated();
+                InvokeLayerBitmapChange();
             }
         }
 
@@ -121,6 +119,7 @@ namespace PixiEditor.Models.Layers
                             new object[] { LayerGuid },
                             "Change layer visibility"));
                     IsVisible = value;
+                    InvokeLayerBitmapChange();
                 }
             }
         }
@@ -151,12 +150,10 @@ namespace PixiEditor.Models.Layers
             get => opacity;
             set
             {
-                if (SetProperty(ref opacity, value))
-                {
-                    RaisePropertyChanged(nameof(OpacityUndoTriggerable));
-                    InvokeLayerBitmapChange();
-                    ViewModelMain.Current.ToolsSubViewModel.TriggerCacheOutdated();
-                }
+                opacity = value;
+                RaisePropertyChanged(nameof(OpacityUndoTriggerable));
+                ViewModelMain.Current?.ToolsSubViewModel?.TriggerCacheOutdated();
+                InvokeLayerBitmapChange();
             }
         }
 
@@ -192,6 +189,7 @@ namespace PixiEditor.Models.Layers
             {
                 offset = value;
                 RaisePropertyChanged("Offset");
+                InvokeLayerBitmapChange();
             }
         }
 
@@ -445,6 +443,7 @@ namespace PixiEditor.Models.Layers
         {
             LayerBitmap.SkiaSurface.Canvas.Clear();
             ClipCanvas();
+            InvokeLayerBitmapChange();
         }
 
         /// <summary>

+ 30 - 5
PixiEditor/Models/Layers/Utils/LayerStructureUtils.cs

@@ -1,8 +1,4 @@
 using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace PixiEditor.Models.Layers.Utils
 {
@@ -32,5 +28,34 @@ namespace PixiEditor.Models.Layers.Utils
 
             return Math.Clamp(finalOpacity, 0f, 1f);
         }
+
+        /// <summary>
+        /// Gets final layer IsVisible taking into consideration group visibility.
+        /// </summary>
+        /// <param name="layer">Layer to check.</param>
+        /// <returns>True if is visible, false if at least parent is not visible or layer itself is invisible.</returns>
+        public static bool GetFinalLayerIsVisible(Layer layer, LayerStructure structure)
+        {
+            if (!layer.IsVisible)
+            {
+                return false;
+            }
+
+            var group = structure.GetGroupByLayer(layer.LayerGuid);
+            bool atLeastOneParentIsInvisible = false;
+            GuidStructureItem groupToCheck = group;
+            while (groupToCheck != null)
+            {
+                if (!groupToCheck.IsVisible)
+                {
+                    atLeastOneParentIsInvisible = true;
+                    break;
+                }
+
+                groupToCheck = groupToCheck.Parent;
+            }
+
+            return !atLeastOneParentIsInvisible;
+        }
     }
-}
+}

+ 4 - 5
PixiEditor/Models/Position/CoordinatesCalculator.cs

@@ -1,5 +1,4 @@
 using PixiEditor.Models.DataHolders;
-using SkiaSharp;
 using System;
 using System.Collections.Generic;
 
@@ -90,7 +89,7 @@ namespace PixiEditor.Models.Position
             {
                 for (int x = 0; x < bitmap.Width; x++)
                 {
-                    if (bitmap.GetSRGBPixel(x, y) != SKColors.Transparent)
+                    if (bitmap.GetSRGBPixel(x, y).Alpha != 0)
                     {
                         return y;
                     }
@@ -106,7 +105,7 @@ namespace PixiEditor.Models.Position
             {
                 for (int y = 0; y < bitmap.Height; y++)
                 {
-                    if (bitmap.GetSRGBPixel(x, y) != SKColors.Transparent)
+                    if (bitmap.GetSRGBPixel(x, y).Alpha != 0)
                     {
                         return x;
                     }
@@ -122,7 +121,7 @@ namespace PixiEditor.Models.Position
             {
                 for (int x = bitmap.Width - 1; x >= 0; x--)
                 {
-                    if (bitmap.GetSRGBPixel(x, y) != SKColors.Transparent)
+                    if (bitmap.GetSRGBPixel(x, y).Alpha != 0)
                     {
                         return y;
                     }
@@ -138,7 +137,7 @@ namespace PixiEditor.Models.Position
             {
                 for (int y = bitmap.Height - 1; y >= 0; y--)
                 {
-                    if (bitmap.GetSRGBPixel(x, y) != SKColors.Transparent)
+                    if (bitmap.GetSRGBPixel(x, y).Alpha != 0)
                     {
                         return x;
                     }

+ 3 - 5
PixiEditor/Models/Tools/Tool.cs

@@ -1,12 +1,10 @@
-using System;
-using System.Text;
-using System.Windows.Input;
-using PixiEditor.Helpers;
+using PixiEditor.Helpers;
 using PixiEditor.Helpers.Extensions;
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.Position;
 using PixiEditor.Models.Tools.ToolSettings;
 using PixiEditor.Models.Tools.ToolSettings.Toolbars;
+using System.Windows.Input;
 
 namespace PixiEditor.Models.Tools
 {
@@ -87,4 +85,4 @@ namespace PixiEditor.Models.Tools
         {
         }
     }
-}
+}

+ 8 - 6
PixiEditor/Models/Tools/Tools/ColorPickerTool.cs

@@ -3,7 +3,7 @@ using PixiEditor.ViewModels;
 using SkiaSharp;
 using System.Collections.Generic;
 using System.Drawing;
-using System.Windows.Input;
+using System.Linq;
 
 namespace PixiEditor.Models.Tools.Tools
 {
@@ -18,15 +18,17 @@ namespace PixiEditor.Models.Tools.Tools
 
         public override string Tooltip => "Swaps primary color with selected on canvas. (O)";
 
-        public override void OnMouseDown(MouseEventArgs e)
+
+        public override void Use(List<Coordinates> coordinates)
         {
-            base.OnMouseDown(e);
-            ViewModelMain.Current.ColorsSubViewModel.PrimaryColor = GetColorUnderMouse();
+            var coords = coordinates.First();
+            ViewModelMain.Current.ColorsSubViewModel.PrimaryColor = GetColorAt(coords.X, coords.Y);
         }
 
-        public override void Use(List<Coordinates> coordinates)
+        public SKColor GetColorAt(int x, int y)
         {
-            ViewModelMain.Current.ColorsSubViewModel.PrimaryColor = GetColorUnderMouse();
+            var color = ViewModelMain.Current.BitmapManager?.ActiveDocument?.Renderer?.FinalSurface.GetSRGBPixel(x, y);
+            return color.HasValue ? color.Value : SKColors.Transparent;
         }
 
         public SKColor GetColorUnderMouse()

+ 5 - 5
PixiEditor/Models/Undo/StorageBasedChange.cs

@@ -20,14 +20,14 @@ namespace PixiEditor.Models.Undo
 
         public UndoLayer[] StoredLayers { get; set; }
 
-        private IEnumerable<Guid> layersToStore;
+        private List<Guid> layersToStore;
 
         private Document document;
 
         public StorageBasedChange(Document doc, IEnumerable<Layer> layers, bool saveOnStartup = true)
         {
             document = doc;
-            layersToStore = layers.Select(x => x.LayerGuid);
+            layersToStore = layers.Select(x => x.LayerGuid).ToList();
             UndoChangeLocation = DefaultUndoChangeLocation;
             GenerateUndoLayers();
             if (saveOnStartup)
@@ -39,7 +39,7 @@ namespace PixiEditor.Models.Undo
         public StorageBasedChange(Document doc, IEnumerable<Layer> layers, string undoChangeLocation, bool saveOnStartup = true)
         {
             document = doc;
-            layersToStore = layers.Select(x => x.LayerGuid);
+            layersToStore = layers.Select(x => x.LayerGuid).ToList();
             UndoChangeLocation = undoChangeLocation;
             GenerateUndoLayers();
 
@@ -64,7 +64,7 @@ namespace PixiEditor.Models.Undo
                 i++;
             }
 
-            layersToStore = Array.Empty<Guid>();
+            layersToStore = new List<Guid>();
         }
 
         /// <summary>
@@ -95,7 +95,7 @@ namespace PixiEditor.Models.Undo
                 File.Delete(StoredLayers[i].StoredPngLayerName);
             }
 
-            layersToStore = layers.Select(x => x.LayerGuid);
+            layersToStore = layers.Select(x => x.LayerGuid).ToList();
             return layers;
         }
 

+ 10 - 5
PixiEditor/ViewModels/SubViewModels/Main/IoViewModel.cs

@@ -1,9 +1,9 @@
-using System;
-using System.Windows;
-using System.Windows.Input;
-using PixiEditor.Helpers;
+using PixiEditor.Helpers;
 using PixiEditor.Models.Controllers.Shortcuts;
 using PixiEditor.Models.Position;
+using System;
+using System.Windows;
+using System.Windows.Input;
 
 namespace PixiEditor.ViewModels.SubViewModels.Main
 {
@@ -79,6 +79,11 @@ namespace PixiEditor.ViewModels.SubViewModels.Main
                 Mouse.PrimaryDevice,
                 (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds()));
 
+            Coordinates cords = new Coordinates(
+                (int)Owner.BitmapManager.ActiveDocument.MouseXOnCanvas,
+                (int)Owner.BitmapManager.ActiveDocument.MouseYOnCanvas);
+            Owner.BitmapManager.MouseController.MouseDownCoordinates(cords);
+
             // Mouse down is guaranteed to only be raised from within this application, so by subscribing here we
             // only listen for mouse up events that occurred as a result of a mouse down within this application.
             // This seems better than maintaining a global listener indefinitely.
@@ -123,4 +128,4 @@ namespace PixiEditor.ViewModels.SubViewModels.Main
             Owner.BitmapManager.SelectedTool.OnKeyUp(args);
         }
     }
-}
+}

+ 2 - 1
PixiEditor/Views/MainWindow.xaml

@@ -31,6 +31,7 @@
             <converters:IsSpecifiedTypeConverter SpecifiedType="{x:Type tools:ZoomTool}" x:Key="IsZoomToolConverter"/>
             <converters:IsSpecifiedTypeConverter SpecifiedType="{x:Type tools:MoveViewportTool}" x:Key="IsMoveViewportToolConverter"/>
             <converters:SKColorToMediaColorConverter x:Key="SKColorToMediaColorConverter"/>
+            <converters:DockingManagerActiveContentConverter x:Key="DockingManagerActiveContentConverter"/>
             <ResourceDictionary.MergedDictionaries>
                 <ResourceDictionary Source="pack://application:,,,/ColorPicker;component/Styles/DefaultColorPickerStyle.xaml" />
             </ResourceDictionary.MergedDictionaries>
@@ -240,7 +241,7 @@
         </StackPanel>
         <Grid Grid.Column="1" Grid.Row="2" Background="#303030">
             <Grid AllowDrop="True" Drop="MainWindow_Drop">
-                <DockingManager ActiveContent="{Binding BitmapManager.ActiveDocument, Mode=TwoWay}" 
+                <DockingManager ActiveContent="{Binding BitmapManager.ActiveDocument, Mode=TwoWay, Converter={StaticResource DockingManagerActiveContentConverter}}" 
                                            DocumentsSource="{Binding BitmapManager.Documents}">
                     <DockingManager.Theme>
                         <avalonDockTheme:PixiEditorDockTheme />

+ 5 - 6
PixiEditor/Views/UserControls/DrawingViewPort.xaml

@@ -66,12 +66,11 @@
 
                 <Image VerticalAlignment="Top" HorizontalAlignment="Left" Source="{Binding Renderer.FinalBitmap}"
                                                RenderOptions.BitmapScalingMode="NearestNeighbor" Stretch="Uniform" />
-                <Image VerticalAlignment="Top" HorizontalAlignment="Left" 
-                           Source="{Binding ActiveSelection.SelectionLayer.LayerBitmap}"
-                                   RenderOptions.BitmapScalingMode="NearestNeighbor" Stretch="Uniform"
-                                   Width="{Binding ActiveSelection.SelectionLayer.Width}"
-                                   Height="{Binding ActiveSelection.SelectionLayer.Height}" 
-                                   Margin="{Binding ActiveSelection.SelectionLayer.Offset}" />
+                <local:PlainLayerView TargetLayer="{Binding ActiveSelection.SelectionLayer}"
+                                         VerticalAlignment="Top" HorizontalAlignment="Left"
+                                         Width="{Binding ActiveSelection.SelectionLayer.Width}"
+                                         Height="{Binding ActiveSelection.SelectionLayer.Height}" 
+                                         Margin="{Binding ActiveSelection.SelectionLayer.Offset}" />
                 <Grid ShowGridLines="True" Width="{Binding Width}" Height="{Binding Height}" Panel.ZIndex="10" 
                       Visibility="{Binding GridLinesVisible, Converter={StaticResource BoolToVisibilityConverter}, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:DrawingViewPort}}}">
                     <Rectangle Focusable="False">

+ 1 - 1
PixiEditor/Views/UserControls/Layers/LayerGroupControl.xaml.cs

@@ -292,7 +292,7 @@ namespace PixiEditor.Views.UserControls.Layers
 
                 foreach (var layer in layers)
                 {
-                    layer.RaisePropertyChange(nameof(layer.IsVisible));
+                    layer.IsVisible = layer.IsVisible;
                 }
 
                 IsVisibleUndoTriggerable = value;

+ 4 - 2
PixiEditor/Views/UserControls/Layers/LayerItem.xaml

@@ -4,6 +4,7 @@
              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
              xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
              xmlns:local="clr-namespace:PixiEditor.Views"
+             xmlns:controls="clr-namespace:PixiEditor.Views.UserControls"
              xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:behaviors="clr-namespace:PixiEditor.Helpers.Behaviours" xmlns:layers="clr-namespace:PixiEditor.Models.Layers" xmlns:helpers="clr-namespace:PixiEditor.Helpers.UI"
              mc:Ignorable="d" Focusable="True"
              d:DesignHeight="60" d:DesignWidth="250" Name="uc"
@@ -39,8 +40,9 @@
                     <Rectangle Width="{Binding Path=(helpers:TreeViewItemHelper.Indent).Value, Mode=OneWay, RelativeSource={RelativeSource AncestorType=ItemsPresenter}}" Fill="Transparent" StrokeThickness="0"/>
                     <Border Width="30" Height="30" BorderThickness="1" BorderBrush="Black" Background="{StaticResource MainColor}"
                            Margin="5, 0, 10, 0">
-                        <Image Source="{Binding PreviewImage,ElementName=uc}" Stretch="Uniform" Width="20" Height="20" 
-                       RenderOptions.BitmapScalingMode="NearestNeighbor"/>
+                        <controls:PlainLayerView TargetLayer="{Binding LayerForPreview, ElementName=uc}"/>
+                        <!--<Image Source="{Binding PreviewImage,ElementName=uc}" Stretch="Uniform" Width="20" Height="20"
+                       RenderOptions.BitmapScalingMode="NearestNeighbor"/>-->
                     </Border>
 
                     <local:EditableTextBlock

+ 16 - 17
PixiEditor/Views/UserControls/Layers/LayerItem.xaml.cs

@@ -1,12 +1,11 @@
 using PixiEditor.Helpers;
 using PixiEditor.Models.DataHolders;
-using PixiEditor.Views.UserControls;
+using PixiEditor.Models.Layers;
 using System;
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Input;
 using System.Windows.Media;
-using System.Windows.Media.Imaging;
 
 namespace PixiEditor.Views.UserControls.Layers
 {
@@ -23,7 +22,7 @@ namespace PixiEditor.Views.UserControls.Layers
         }
 
         public static readonly DependencyProperty IsRenamingProperty = DependencyProperty.Register(
-            "IsRenaming", typeof(bool), typeof(LayerItem), new PropertyMetadata(default(bool)));
+            nameof(IsRenaming), typeof(bool), typeof(LayerItem), new PropertyMetadata(default(bool)));
 
         public bool IsRenaming
         {
@@ -32,7 +31,7 @@ namespace PixiEditor.Views.UserControls.Layers
         }
 
         public static readonly DependencyProperty IsActiveProperty = DependencyProperty.Register(
-            "IsActive", typeof(bool), typeof(LayerItem), new PropertyMetadata(default(bool)));
+            nameof(IsActive), typeof(bool), typeof(LayerItem), new PropertyMetadata(default(bool)));
 
         public bool IsActive
         {
@@ -41,7 +40,7 @@ namespace PixiEditor.Views.UserControls.Layers
         }
 
         public static readonly DependencyProperty SetActiveLayerCommandProperty = DependencyProperty.Register(
-            "SetActiveLayerCommand", typeof(RelayCommand), typeof(LayerItem), new PropertyMetadata(default(RelayCommand)));
+            nameof(SetActiveLayerCommand), typeof(RelayCommand), typeof(LayerItem), new PropertyMetadata(default(RelayCommand)));
 
         public RelayCommand SetActiveLayerCommand
         {
@@ -50,7 +49,7 @@ namespace PixiEditor.Views.UserControls.Layers
         }
 
         public static readonly DependencyProperty LayerIndexProperty = DependencyProperty.Register(
-            "LayerIndex", typeof(int), typeof(LayerItem), new PropertyMetadata(default(int)));
+            nameof(LayerIndex), typeof(int), typeof(LayerItem), new PropertyMetadata(default(int)));
 
         public int LayerIndex
         {
@@ -59,7 +58,7 @@ namespace PixiEditor.Views.UserControls.Layers
         }
 
         public static readonly DependencyProperty LayerNameProperty = DependencyProperty.Register(
-            "LayerName", typeof(string), typeof(LayerItem), new PropertyMetadata(default(string)));
+            nameof(LayerName), typeof(string), typeof(LayerItem), new PropertyMetadata(default(string)));
 
         public string LayerName
         {
@@ -74,19 +73,19 @@ namespace PixiEditor.Views.UserControls.Layers
         }
 
         public static readonly DependencyProperty LayerGuidProperty =
-            DependencyProperty.Register("LayerGuid", typeof(Guid), typeof(LayerItem), new PropertyMetadata(default(Guid)));
+            DependencyProperty.Register(nameof(LayerGuid), typeof(Guid), typeof(LayerItem), new PropertyMetadata(default(Guid)));
 
         public static readonly DependencyProperty ControlButtonsVisibleProperty = DependencyProperty.Register(
-            "ControlButtonsVisible", typeof(Visibility), typeof(LayerItem), new PropertyMetadata(System.Windows.Visibility.Hidden));
+            nameof(ControlButtonsVisible), typeof(Visibility), typeof(LayerItem), new PropertyMetadata(System.Windows.Visibility.Hidden));
 
-        public WriteableBitmap PreviewImage
+        public Layer LayerForPreview
         {
-            get { return (WriteableBitmap)GetValue(PreviewImageProperty); }
-            set { SetValue(PreviewImageProperty, value); }
+            get { return (Layer)GetValue(LayerForPreviewProperty); }
+            set { SetValue(LayerForPreviewProperty, value); }
         }
 
-        public static readonly DependencyProperty PreviewImageProperty =
-            DependencyProperty.Register("PreviewImage", typeof(WriteableBitmap), typeof(LayerItem), new PropertyMetadata(null));
+        public static readonly DependencyProperty LayerForPreviewProperty =
+            DependencyProperty.Register(nameof(LayerForPreview), typeof(Layer), typeof(LayerItem), new PropertyMetadata(null));
 
         public string LayerColor
         {
@@ -95,7 +94,7 @@ namespace PixiEditor.Views.UserControls.Layers
         }
 
         public static readonly DependencyProperty LayerColorProperty =
-            DependencyProperty.Register("LayerColor", typeof(string), typeof(LayerItem), new PropertyMetadata("#00000000"));
+            DependencyProperty.Register(nameof(LayerColor), typeof(string), typeof(LayerItem), new PropertyMetadata("#00000000"));
 
         public Visibility ControlButtonsVisible
         {
@@ -110,10 +109,10 @@ namespace PixiEditor.Views.UserControls.Layers
         }
 
         public static readonly DependencyProperty MoveToBackCommandProperty =
-            DependencyProperty.Register("MoveToBackCommand", typeof(RelayCommand), typeof(LayerItem), new PropertyMetadata(default(RelayCommand)));
+            DependencyProperty.Register(nameof(MoveToBackCommand), typeof(RelayCommand), typeof(LayerItem), new PropertyMetadata(default(RelayCommand)));
 
         public static readonly DependencyProperty MoveToFrontCommandProperty = DependencyProperty.Register(
-            "MoveToFrontCommand", typeof(RelayCommand), typeof(LayerItem), new PropertyMetadata(default(RelayCommand)));
+            nameof(MoveToFrontCommand), typeof(RelayCommand), typeof(LayerItem), new PropertyMetadata(default(RelayCommand)));
 
         public RelayCommand MoveToFrontCommand
         {

+ 1 - 1
PixiEditor/Views/UserControls/Layers/LayerStructureItemContainer.xaml

@@ -11,7 +11,7 @@
                                        LayerName="{Binding Name, Mode=TwoWay}" 
                                        IsActive="{Binding IsActive, Mode=TwoWay}"
                                        IsRenaming="{Binding IsRenaming, Mode=TwoWay}"
-                                       PreviewImage="{Binding LayerBitmap}"
+                                       LayerForPreview="{Binding}"
                                        LayerGuid="{Binding LayerGuid}"
                                        LayerColor="{Binding LayerHighlightColor}"
                                        LayerIndex="{Binding ContainerIndex, ElementName=layerStructureContainer}"

+ 12 - 0
PixiEditor/Views/UserControls/PlainLayerView.xaml

@@ -0,0 +1,12 @@
+<UserControl x:Class="PixiEditor.Views.UserControls.PlainLayerView"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+             xmlns:local="clr-namespace:PixiEditor.Views.UserControls"
+             mc:Ignorable="d" 
+             x:Name="uc"
+             d:DesignHeight="450" d:DesignWidth="800">
+    <Image x:Name="image" Width="{Binding Width, ElementName=uc}" Height="{Binding Height, ElementName=uc}" 
+           RenderOptions.BitmapScalingMode="NearestNeighbor" Stretch="Uniform"/>
+</UserControl>

+ 105 - 0
PixiEditor/Views/UserControls/PlainLayerView.xaml.cs

@@ -0,0 +1,105 @@
+using PixiEditor.Models.Controllers;
+using PixiEditor.Models.Layers;
+using System;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace PixiEditor.Views.UserControls
+{
+    public partial class PlainLayerView : UserControl
+    {
+        public static readonly DependencyProperty TargetLayerProperty =
+            DependencyProperty.Register(nameof(TargetLayer), typeof(Layer), typeof(PlainLayerView), new PropertyMetadata(null, OnLayerChanged));
+
+        public Layer TargetLayer
+        {
+            get => (Layer)GetValue(TargetLayerProperty);
+            set => SetValue(TargetLayerProperty, value);
+        }
+
+        private SurfaceRenderer renderer;
+
+        public PlainLayerView()
+        {
+            InitializeComponent();
+            SizeChanged += OnControlSizeChanged;
+            Unloaded += OnControlUnloaded;
+        }
+
+        private static void OnLayerChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
+        {
+            var view = (PlainLayerView)sender;
+            if (args.OldValue != null)
+                ((Layer)args.OldValue).LayerBitmapChanged -= view.OnLayerBitmapChanged;
+            if (args.NewValue != null)
+            {
+                var layer = ((Layer)args.NewValue);
+                layer.LayerBitmapChanged += view.OnLayerBitmapChanged;
+                view.Resize(layer.Width, layer.Height);
+            }
+        }
+        public void Resize(int newWidth, int newHeight)
+        {
+            renderer?.Dispose();
+            renderer = new SurfaceRenderer(newWidth, newHeight);
+            image.Source = renderer.FinalBitmap;
+            Update();
+        }
+
+        private void Update()
+        {
+            renderer.Draw(TargetLayer.LayerBitmap, (byte)(TargetLayer.Opacity * 255));
+        }
+
+        private void OnControlUnloaded(object sender, RoutedEventArgs e)
+        {
+            /*
+            if (LogicalTreeHelper.GetParent(this) != null)
+                return;
+            renderer?.Dispose();
+            TargetLayer.LayerBitmapChanged -= OnLayerBitmapChanged;*/
+        }
+
+        private void OnControlSizeChanged(object sender, SizeChangedEventArgs e)
+        {
+            if (TargetLayer == null)
+                return;
+            MaybeResize(e.NewSize);
+        }
+
+        private bool MaybeResize(Size newSize)
+        {
+            var (w, h) = GetOptimizedDimensions(TargetLayer.Width, TargetLayer.Height, newSize.Width, newSize.Height);
+            Resize(w, h);
+            return true;
+        }
+
+        private (int, int) GetOptimizedDimensions(int width, int height, double viewWidth, double viewHeight)
+        {
+            if (width <= viewWidth && height <= viewHeight)
+                return (width, height);
+
+            double frac = width / (double)height;
+            double viewFrac = viewWidth / viewHeight;
+
+            if (frac > viewFrac)
+            {
+                double targetWidth = viewWidth;
+                double targetHeight = viewWidth / frac;
+                return ((int)Math.Ceiling(targetWidth), (int)Math.Ceiling(targetHeight));
+            }
+            else
+            {
+                double targetHeight = viewHeight;
+                double targetWidth = targetHeight * frac;
+                return ((int)Math.Ceiling(targetWidth), (int)Math.Ceiling(targetHeight));
+            }
+        }
+
+        private void OnLayerBitmapChanged(object sender, Int32Rect e)
+        {
+            if (!MaybeResize(RenderSize))
+                Update();
+        }
+    }
+}

+ 13 - 30
PixiEditor/Views/UserControls/PreviewWindow.xaml

@@ -13,6 +13,7 @@
     <UserControl.Resources>
         <BoolToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
         <converters:NotNullToVisibilityConverter x:Key="NullToVisibilityConverter"/>
+        <converters:ViewboxInverseTransformConverter x:Key="ViewboxToScaleConverter"/>
     </UserControl.Resources>
     <Grid>
         <Grid.RowDefinitions>
@@ -21,38 +22,20 @@
             <RowDefinition Height="Auto"/>
         </Grid.RowDefinitions>
 
-        <Viewbox Margin="30" VerticalAlignment="Center">
+        <Viewbox Margin="30" VerticalAlignment="Center" x:Name="previewWindowViewbox">
             <Grid x:Name="imageGrid" RenderOptions.BitmapScalingMode="NearestNeighbor"
               Visibility="{Binding Document, Converter={StaticResource NullToVisibilityConverter}, ElementName=uc}"
               Height="{Binding Document.Height, ElementName=uc}" Width="{Binding Document.Width, ElementName=uc}"
-              Background="{Binding ActiveItem.Value, ElementName=backgroundButton}" d:Width="8" d:Height="8">
-                <!--<ItemsControl ItemsSource="{Binding Document.Layers, ElementName=uc}">
-                    <ItemsControl.ItemsPanel>
-                        <ItemsPanelTemplate>
-                            <Grid/>
-                        </ItemsPanelTemplate>
-                    </ItemsControl.ItemsPanel>
-                    <ItemsControl.ItemTemplate>
-                        <DataTemplate>
-                            <Image VerticalAlignment="Top" HorizontalAlignment="Left" Source="{Binding LayerBitmap}"
-                                               RenderOptions.BitmapScalingMode="NearestNeighbor" Stretch="Uniform"
-                                               Width="{Binding Width}" Height="{Binding Height}" Margin="{Binding Offset}">
-                                <Image.Opacity>
-                                    <MultiBinding Converter="{converters:LayerToFinalOpacityConverter}">
-                                        <Binding Path="."/>
-                                        <Binding Path="Opacity"/>
-                                    </MultiBinding>
-                                </Image.Opacity>
-                                <Image.Visibility>
-                                    <MultiBinding Converter="{converters:FinalIsVisibleToVisiblityConverter}">
-                                        <Binding Path="."/>
-                                        <Binding Path="IsVisible"/>
-                                    </MultiBinding>
-                                </Image.Visibility>
-                            </Image>
-                        </DataTemplate>
-                    </ItemsControl.ItemTemplate>
-                </ItemsControl>-->
+              d:Width="8" d:Height="8">
+                <Grid Background="{Binding ActiveItem.Value, ElementName=backgroundButton}">
+                    <Grid.LayoutTransform>
+                        <MultiBinding Converter="{StaticResource ViewboxToScaleConverter}">
+                            <Binding ElementName="previewWindowViewbox" Path="." />
+                            <Binding ElementName="imageGrid" Path="ActualWidth" />
+                            <Binding ElementName="imageGrid" Path="ActualHeight" />
+                        </MultiBinding>
+                    </Grid.LayoutTransform>
+                </Grid>
                 <Image VerticalAlignment="Top" HorizontalAlignment="Left" Source="{Binding Document.Renderer.FinalBitmap, ElementName=uc}"
                                                RenderOptions.BitmapScalingMode="NearestNeighbor" Stretch="Uniform" />
                 <Border x:Name="colorCursor" Width="1" Height="1"
@@ -108,7 +91,7 @@
                                     <ImageBrush ImageSource="/Images/CheckerTile.png" TileMode="Tile" Viewport="0, 0, 1, 1"/>
                                 </local:SwitchItem.Background>
                                 <local:SwitchItem.Value>
-                                    <ImageBrush Viewport="0, 0.05, 0.05, 0.05" ImageSource="/Images/CheckerTile.png" TileMode="Tile"/>
+                                    <ImageBrush Viewport="0, 10, 10, 10" ImageSource="/Images/CheckerTile.png" TileMode="Tile" ViewportUnits="Absolute"/>
                                 </local:SwitchItem.Value>
                             </local:SwitchItem>
                             <local:SwitchItem Value="Transparent">

+ 7 - 17
PixiEditorTests/ModelsTests/ColorsTests/ExtendedColorTests.cs

@@ -1,36 +1,26 @@
-using System;
-using System.Windows.Media;
-using PixiEditor.Models.Colors;
+using PixiEditor.Models.Colors;
 using SkiaSharp;
+using System;
 using Xunit;
 
 namespace PixiEditorTests.ModelsTests.ColorsTests
 {
     public class ExtendedColorTests
     {
-
-        public static readonly SKColor white = new SKColor(255, 255, 255);
-        public static readonly SKColor black = new SKColor(0, 0, 0);
-        public static readonly SKColor transparent = new SKColor(0, 0, 0, 0);
-        public static readonly SKColor red = new SKColor(255, 0, 0);
-        public static readonly SKColor green = new SKColor(0, 255, 0);
-        public static readonly SKColor blue = new SKColor(0, 0, 255);
-
         private const int AcceptableMaringOfError = 1;
 
-
         [Fact]
         public void ChangeColorBrightnessIsNotTheSameTest()
         {
-            SKColor newColor = ExColor.ChangeColorBrightness(white, -1);
-            Assert.NotEqual(white, newColor);
+            SKColor newColor = ExColor.ChangeColorBrightness(SKColors.White, -1);
+            Assert.NotEqual(SKColors.White, newColor);
         }
 
         [Fact]
         public void ChangeColorBrightnessNewValueTest()
         {
-            SKColor newColor = ExColor.ChangeColorBrightness(white, -100);
-            Assert.Equal(black, newColor);
+            SKColor newColor = ExColor.ChangeColorBrightness(SKColors.White, -100);
+            Assert.Equal(SKColors.Black, newColor);
         }
 
         // Acceptable margin of error is 1
@@ -68,4 +58,4 @@ namespace PixiEditorTests.ModelsTests.ColorsTests
             Assert.True(marginOfErrorB <= AcceptableMaringOfError);
         }
     }
-}
+}

+ 9 - 10
PixiEditorTests/ModelsTests/ControllersTests/BitmapManagerTests.cs

@@ -1,10 +1,7 @@
-using System.Windows.Media;
-using PixiEditor.Models.Controllers;
+using PixiEditor.Models.Controllers;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.Position;
-using PixiEditor.Models.Tools;
-using PixiEditor.Models.Undo;
-using PixiEditorTests.ModelsTests.ColorsTests;
+using SkiaSharp;
 using Xunit;
 
 namespace PixiEditorTests.ModelsTests.ControllersTests
@@ -30,7 +27,8 @@ namespace PixiEditorTests.ModelsTests.ControllersTests
             bitmapManager.ActiveDocument.AddNewLayer(layerName);
             Assert.Single(bitmapManager.ActiveDocument.Layers);
             Assert.Equal(layerName, bitmapManager.ActiveDocument.ActiveLayer.Name);
-            Assert.Equal(0, bitmapManager.ActiveDocument.ActiveLayer.Width + bitmapManager.ActiveDocument.ActiveLayer.Height);
+            Assert.Equal(1, bitmapManager.ActiveDocument.ActiveLayer.Width);
+            Assert.Equal(1, bitmapManager.ActiveDocument.ActiveLayer.Height);
         }
 
         [Fact]
@@ -56,7 +54,8 @@ namespace PixiEditorTests.ModelsTests.ControllersTests
             };
             bitmapManager.ActiveDocument.GeneratePreviewLayer();
             Assert.NotNull(bitmapManager.ActiveDocument.PreviewLayer);
-            Assert.Equal(0, bitmapManager.ActiveDocument.PreviewLayer.Width + bitmapManager.ActiveDocument.PreviewLayer.Height); // Size is zero
+            Assert.Equal(1, bitmapManager.ActiveDocument.PreviewLayer.Width); // Size is 1x1
+            Assert.Equal(1, bitmapManager.ActiveDocument.PreviewLayer.Height);
             Assert.Equal(0, bitmapManager.ActiveDocument.PreviewLayer.OffsetX + bitmapManager.ActiveDocument.PreviewLayer.OffsetY); // Offset is zero
             Assert.Equal(bitmapManager.ActiveDocument.Width, bitmapManager.ActiveDocument.PreviewLayer.MaxWidth);
             Assert.Equal(bitmapManager.ActiveDocument.Height, bitmapManager.ActiveDocument.PreviewLayer.MaxHeight);
@@ -84,7 +83,7 @@ namespace PixiEditorTests.ModelsTests.ControllersTests
 
             bitmapManager.ActiveDocument.AddNewLayer("Layer");
             bitmapManager.SetActiveTool(new MockedSinglePixelPenTool());
-            bitmapManager.PrimaryColor = ExtendedColorTests.black;
+            bitmapManager.PrimaryColor = SKColors.Black;
 
             bitmapManager.MouseController.StartRecordingMouseMovementChanges(true);
             bitmapManager.MouseController.RecordMouseMovementChange(new Coordinates(1, 1));
@@ -92,7 +91,7 @@ namespace PixiEditorTests.ModelsTests.ControllersTests
 
             bitmapManager.ExecuteTool(new Coordinates(1, 1), true);
 
-            Assert.Equal(ExtendedColorTests.black, bitmapManager.ActiveLayer.GetPixelWithOffset(1, 1));
+            Assert.Equal(SKColors.Black, bitmapManager.ActiveLayer.GetPixelWithOffset(1, 1));
         }
     }
-}
+}

+ 7 - 8
PixiEditorTests/ModelsTests/ControllersTests/BitmapOperationsUtilityTests.cs

@@ -1,10 +1,9 @@
-using System.Collections.Generic;
-using System.Windows.Media;
-using PixiEditor.Models.Controllers;
+using PixiEditor.Models.Controllers;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.Layers;
 using PixiEditor.Models.Position;
-using PixiEditorTests.ModelsTests.ColorsTests;
+using SkiaSharp;
+using System.Collections.Generic;
 using Xunit;
 
 namespace PixiEditorTests.ModelsTests.ControllersTests
@@ -19,7 +18,7 @@ namespace PixiEditorTests.ModelsTests.ControllersTests
 
             Layer testLayer = new Layer("test layer", 10, 10);
             Coordinates[] cords = { new Coordinates(0, 0), new Coordinates(1, 1) };
-            BitmapPixelChanges pixels = BitmapPixelChanges.FromSingleColoredArray(cords, ExtendedColorTests.black);
+            BitmapPixelChanges pixels = BitmapPixelChanges.FromSingleColoredArray(cords, SKColors.Black);
             testLayer.SetPixels(pixels);
 
             util.DeletePixels(new[] { testLayer }, cords);
@@ -34,7 +33,7 @@ namespace PixiEditorTests.ModelsTests.ControllersTests
             BitmapManager manager = new BitmapManager
             {
                 ActiveDocument = new Document(10, 10),
-                PrimaryColor = ExtendedColorTests.black
+                PrimaryColor = SKColors.Black
             };
             manager.ActiveDocument.AddNewLayer("Test layer", 10, 10);
 
@@ -43,7 +42,7 @@ namespace PixiEditorTests.ModelsTests.ControllersTests
             List<Coordinates> mouseMove = new List<Coordinates>(new[] { new Coordinates(0, 0) });
 
             util.ExecuteTool(new Coordinates(0, 0), mouseMove, new MockedSinglePixelPenTool());
-            Assert.Equal(manager.ActiveLayer.GetPixel(0, 0), ExtendedColorTests.black);
+            Assert.Equal(manager.ActiveLayer.GetPixel(0, 0), SKColors.Black);
         }
     }
-}
+}

+ 10 - 10
PixiEditorTests/ModelsTests/ControllersTests/ClipboardControllerTests.cs

@@ -65,7 +65,7 @@ namespace PixiEditorTests.ModelsTests.ControllersTests
             Assert.Equal(2, img.Width);
             Assert.Equal(2, img.Height);
 
-            Surface bmp = new Surface(img);
+            using Surface bmp = new Surface(new WriteableBitmap(img));
             Assert.Equal(testColor, bmp.GetSRGBPixel(0, 0));
             Assert.Equal(testColor, bmp.GetSRGBPixel(1, 1));
         }
@@ -76,27 +76,27 @@ namespace PixiEditorTests.ModelsTests.ControllersTests
             Clipboard.Clear();
             using Surface bmp = new Surface(10, 10);
             bmp.SetSRGBPixel(4, 4, testColor);
-            Clipboard.SetImage(bmp);
+            Clipboard.SetImage(bmp.ToWriteableBitmap());
 
             Surface img = ClipboardController.GetImagesFromClipboard();
             Assert.NotNull(img);
             Assert.Equal(10, img.Width);
             Assert.Equal(10, img.Height);
-            Assert.Equal(testColor, bmp.GetPixel(4, 4));
+            Assert.Equal(testColor, bmp.GetSRGBPixel(4, 4));
         }
 
         [StaFact]
         public void TestThatClipboardControllerGetsCorrectImageInPngFormatFromClipboard()
         {
             Clipboard.Clear();
-            Surface bmp = BitmapFactory.New(10, 10);
-            bmp.SetPixel(4, 4, testColor);
+            using Surface bmp = new Surface(10, 10);
+            bmp.SetSRGBPixel(4, 4, testColor);
             using (MemoryStream pngStream = new MemoryStream())
             {
                 DataObject data = new DataObject();
 
                 PngBitmapEncoder encoder = new PngBitmapEncoder();
-                encoder.Frames.Add(BitmapFrame.Create(bmp));
+                encoder.Frames.Add(BitmapFrame.Create(bmp.ToWriteableBitmap()));
                 encoder.Save(pngStream);
                 data.SetData("PNG", pngStream, false); // PNG, supports transparency
                 Clipboard.SetDataObject(data, true);
@@ -106,15 +106,15 @@ namespace PixiEditorTests.ModelsTests.ControllersTests
             Assert.NotNull(img);
             Assert.Equal(10, img.Width);
             Assert.Equal(10, img.Height);
-            Assert.Equal(testColor, bmp.GetPixel(4, 4));
+            Assert.Equal(testColor, bmp.GetSRGBPixel(4, 4));
         }
 
         [StaFact]
         public void TestThatClipboardControllerGetsCorrectImageInBitmapFormatFromClipboard()
         {
             Clipboard.Clear();
-            Surface bmp = BitmapFactory.New(10, 10);
-            bmp.SetPixel(4, 4, testColor);
+            using Surface bmp = new Surface(10, 10);
+            bmp.SetSRGBPixel(4, 4, testColor);
 
             DataObject data = new DataObject();
             data.SetData(DataFormats.Bitmap, bmp, false); // PNG, supports transparency
@@ -124,7 +124,7 @@ namespace PixiEditorTests.ModelsTests.ControllersTests
             Assert.NotNull(img);
             Assert.Equal(10, img.Width);
             Assert.Equal(10, img.Height);
-            Assert.Equal(testColor, bmp.GetPixel(4, 4));
+            Assert.Equal(testColor, bmp.GetSRGBPixel(4, 4));
         }
     }
 }

+ 10 - 11
PixiEditorTests/ModelsTests/ControllersTests/PixelChangesControllerTests.cs

@@ -1,9 +1,8 @@
-using System;
-using System.Windows.Media;
-using PixiEditor.Models.Controllers;
+using PixiEditor.Models.Controllers;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.Position;
-using PixiEditorTests.ModelsTests.ColorsTests;
+using SkiaSharp;
+using System;
 using Xunit;
 
 namespace PixiEditorTests.ModelsTests.ControllersTests
@@ -30,8 +29,8 @@ namespace PixiEditorTests.ModelsTests.ControllersTests
 
             controller.AddChanges(
                 new LayerChange(
-                    BitmapPixelChanges.FromSingleColoredArray(cords, ExtendedColorTests.black), guid),
-                new LayerChange(BitmapPixelChanges.FromSingleColoredArray(cords, ExtendedColorTests.transparent), guid));
+                    BitmapPixelChanges.FromSingleColoredArray(cords, SKColors.Black), guid),
+                new LayerChange(BitmapPixelChanges.FromSingleColoredArray(cords, SKColors.Transparent), guid));
 
             System.Tuple<LayerChange, LayerChange>[] changes = controller.PopChanges();
             Assert.Equal(2, changes.Length);
@@ -46,8 +45,8 @@ namespace PixiEditorTests.ModelsTests.ControllersTests
 
             controller.AddChanges(
                 new LayerChange(
-                    BitmapPixelChanges.FromSingleColoredArray(cords2, ExtendedColorTests.black), data.Item1),
-                new LayerChange(BitmapPixelChanges.FromSingleColoredArray(cords2, ExtendedColorTests.transparent), data.Item1));
+                    BitmapPixelChanges.FromSingleColoredArray(cords2, SKColors.Black), data.Item1),
+                new LayerChange(BitmapPixelChanges.FromSingleColoredArray(cords2, SKColors.Transparent), data.Item1));
 
             Tuple<LayerChange, LayerChange>[] changes = controller.PopChanges();
             Assert.Single(changes);
@@ -64,9 +63,9 @@ namespace PixiEditorTests.ModelsTests.ControllersTests
 
             controller.AddChanges(
                 new LayerChange(
-                    BitmapPixelChanges.FromSingleColoredArray(cords, ExtendedColorTests.black), guid),
-                new LayerChange(BitmapPixelChanges.FromSingleColoredArray(cords, ExtendedColorTests.transparent), guid));
+                    BitmapPixelChanges.FromSingleColoredArray(cords, SKColors.Black), guid),
+                new LayerChange(BitmapPixelChanges.FromSingleColoredArray(cords, SKColors.Transparent), guid));
             return new Tuple<Guid, PixelChangesController>(guid, controller);
         }
     }
-}
+}

+ 11 - 13
PixiEditorTests/ModelsTests/DataHoldersTests/BitmapPixelChangesTests.cs

@@ -1,8 +1,6 @@
-using System.Windows.Media;
-using PixiEditor.Exceptions;
+using PixiEditor.Exceptions;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.Position;
-using PixiEditorTests.ModelsTests.ColorsTests;
 using SkiaSharp;
 using Xunit;
 
@@ -14,9 +12,9 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
         public void TestThatFromSingleColoredArrayCreatesCorrectArray()
         {
             Coordinates[] cords = { new Coordinates(0, 0), new Coordinates(1, 0), new Coordinates(3, 2) };
-            BitmapPixelChanges bmpChanges = BitmapPixelChanges.FromSingleColoredArray(cords, ExtendedColorTests.green);
+            BitmapPixelChanges bmpChanges = BitmapPixelChanges.FromSingleColoredArray(cords, SKColors.Lime);
 
-            Assert.All(bmpChanges.ChangedPixels.Values, changeColor => Assert.Equal(ExtendedColorTests.green, changeColor));
+            Assert.All(bmpChanges.ChangedPixels.Values, changeColor => Assert.Equal(SKColors.Lime, changeColor));
             Assert.True(bmpChanges.WasBuiltAsSingleColored);
         }
 
@@ -25,28 +23,28 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
         {
             Coordinates[] cords1 = { new Coordinates(0, 0), new Coordinates(1, 0), new Coordinates(3, 2) };
             Coordinates[] cords2 = { new Coordinates(3, 2), new Coordinates(0, 0), new Coordinates(5, 5) };
-            BitmapPixelChanges changes = BitmapPixelChanges.FromSingleColoredArray(cords1, ExtendedColorTests.green);
-            BitmapPixelChanges changes2 = BitmapPixelChanges.FromSingleColoredArray(cords2, ExtendedColorTests.red);
+            BitmapPixelChanges changes = BitmapPixelChanges.FromSingleColoredArray(cords1, SKColors.Lime);
+            BitmapPixelChanges changes2 = BitmapPixelChanges.FromSingleColoredArray(cords2, SKColors.Red);
 
             BitmapPixelChanges output = BitmapPixelChanges.CombineOverride(new[] { changes, changes2 });
             Assert.Equal(4, output.ChangedPixels.Count);
-            Assert.Equal(ExtendedColorTests.red, output.ChangedPixels[new Coordinates(3, 2)]);
-            Assert.Equal(ExtendedColorTests.black, output.ChangedPixels[new Coordinates(0, 0)]);
-            Assert.Equal(ExtendedColorTests.green, output.ChangedPixels[new Coordinates(1, 0)]);
+            Assert.Equal(SKColors.Red, output.ChangedPixels[new Coordinates(3, 2)]);
+            Assert.Equal(SKColors.Red, output.ChangedPixels[new Coordinates(0, 0)]);
+            Assert.Equal(SKColors.Lime, output.ChangedPixels[new Coordinates(1, 0)]);
         }
 
         [Fact]
         public void TestThatFromArraysThrowsError()
         {
             Assert.Throws<ArrayLengthMismatchException>(
-                () => BitmapPixelChanges.FromArrays(new[] { new Coordinates(0, 0) }, new[] { ExtendedColorTests.red, ExtendedColorTests.green }));
+                () => BitmapPixelChanges.FromArrays(new[] { new Coordinates(0, 0) }, new[] { SKColors.Red, SKColors.Lime }));
         }
 
         [Fact]
         public void TestThatFormArraysWorks()
         {
             Coordinates[] coordinatesArray = { new Coordinates(0, 0), new Coordinates(2, 3), new Coordinates(5, 5) };
-            SKColor[] colorsArray = { ExtendedColorTests.red, ExtendedColorTests.green, ExtendedColorTests.blue };
+            SKColor[] colorsArray = { SKColors.Red, SKColors.Lime, SKColors.Blue };
             BitmapPixelChanges result = BitmapPixelChanges.FromArrays(coordinatesArray, colorsArray);
             for (int i = 0; i < coordinatesArray.Length; i++)
             {
@@ -57,4 +55,4 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
             Assert.False(result.WasBuiltAsSingleColored);
         }
     }
-}
+}

+ 13 - 14
PixiEditorTests/ModelsTests/DataHoldersTests/DocumentTests.cs

@@ -1,13 +1,12 @@
-using System;
-using System.Windows.Media;
-using PixiEditor.Models.Controllers;
+using PixiEditor.Models.Controllers;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.Enums;
 using PixiEditor.Models.Layers;
 using PixiEditor.Models.Position;
 using PixiEditor.ViewModels;
 using PixiEditorTests.HelpersTests;
-using PixiEditorTests.ModelsTests.ColorsTests;
+using SkiaSharp;
+using System;
 using Xunit;
 
 namespace PixiEditorTests.ModelsTests.DataHoldersTests
@@ -55,9 +54,9 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
             manager.ActiveLayer.SetPixel(
                 new Coordinates(
                 (int)Math.Ceiling(initialWidth / 2f),
-                (int)Math.Ceiling(initialHeight / 2f)), ExtendedColorTests.black);
+                (int)Math.Ceiling(initialHeight / 2f)), SKColors.Black);
 
-            manager.ActiveLayer.SetPixel(new Coordinates(additionalPixelX, additionalPixelY), ExtendedColorTests.black);
+            manager.ActiveLayer.SetPixel(new Coordinates(additionalPixelX, additionalPixelY), SKColors.Black);
 
             document.ClipCanvas();
 
@@ -81,11 +80,11 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
             manager.ActiveLayer.SetPixel(
                 new Coordinates(
                 (int)Math.Ceiling(initialWidth / 2f),
-                (int)Math.Ceiling(initialHeight / 2f)), ExtendedColorTests.black); // Set pixel in center
+                (int)Math.Ceiling(initialHeight / 2f)), SKColors.Black); // Set pixel in center
 
             manager.ActiveDocument.AddNewLayer("test2");
 
-            manager.ActiveLayer.SetPixel(new Coordinates(secondLayerPixelX, secondLayerPixelY), ExtendedColorTests.black);
+            manager.ActiveLayer.SetPixel(new Coordinates(secondLayerPixelX, secondLayerPixelY), SKColors.Black);
 
             document.ClipCanvas();
 
@@ -114,7 +113,7 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
             };
             manager.ActiveDocument.AddNewLayer("test");
 
-            manager.ActiveLayer.SetPixel(new Coordinates(0, 0), ExtendedColorTests.green);
+            manager.ActiveLayer.SetPixel(new Coordinates(0, 0), SKColors.Lime);
 
             doc.CenterContent();
 
@@ -134,10 +133,10 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
                 ActiveDocument = doc
             };
             manager.ActiveDocument.AddNewLayer("test");
-            manager.ActiveLayer.SetPixel(new Coordinates(0, 0), ExtendedColorTests.green);
+            manager.ActiveLayer.SetPixel(new Coordinates(0, 0), SKColors.Lime);
 
             manager.ActiveDocument.AddNewLayer("test2");
-            manager.ActiveLayer.SetPixel(new Coordinates(1, 1), ExtendedColorTests.green);
+            manager.ActiveLayer.SetPixel(new Coordinates(1, 1), SKColors.Lime);
 
             foreach (var layer in manager.ActiveDocument.Layers)
             {
@@ -322,7 +321,7 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
         {
             const string layerName = "New Layer";
 
-            Document document = new (10, 10);
+            Document document = new(10, 10);
 
             document.AddNewLayer(layerName);
             Layer duplicate = document.DuplicateLayer(0);
@@ -337,7 +336,7 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
         {
             const string layerName = "New Layer";
 
-            Document document = new (10, 10);
+            Document document = new(10, 10);
 
             document.AddNewLayer(layerName);
             document.AddNewLayer(layerName);
@@ -353,4 +352,4 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
             Assert.Equal(layerName + " (16)", document.Layers[4].Name);
         }
     }
-}
+}

+ 15 - 15
PixiEditorTests/ModelsTests/DataHoldersTests/LayerStructureTests.cs

@@ -1,6 +1,6 @@
-using System;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.Layers;
+using System;
 using Xunit;
 
 namespace PixiEditorTests.ModelsTests.DataHoldersTests
@@ -60,7 +60,7 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
         [Fact]
         public void TestThatIsChildOfDetectsNestedGroupCorrectly()
         {
-            LayerStructure ls = new LayerStructure(new Document(0, 0));
+            LayerStructure ls = new LayerStructure(new Document(1, 1));
             Layer testLayer = new Layer("tst");
             ls.Groups.Add(new GuidStructureItem("group 1", testLayer.LayerGuid));
             ls.Groups[0].Subgroups.Add(new GuidStructureItem("group 1 nested", testLayer.LayerGuid));
@@ -72,7 +72,7 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
         [Fact]
         public void TestThatIsChildOfDetectsNestedLayersCorrectly()
         {
-            var doc = new Document(0, 0);
+            var doc = new Document(1, 1);
             doc.Layers.Add(new Layer("tst"));
             Guid testLayerGuid = doc.Layers[0].LayerGuid;
             LayerStructure ls = new LayerStructure(doc);
@@ -86,7 +86,7 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
         [Fact]
         public void TestThatGroupContainsOnlyLayerDetectsOnlySingleLayerCorrectly()
         {
-            var doc = new Document(0, 0);
+            var doc = new Document(1, 1);
             doc.Layers.Add(new Layer("layer"));
             var guid = doc.Layers[0].LayerGuid;
             doc.LayerStructure.AddNewGroup("layer group", guid);
@@ -96,7 +96,7 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
         [Fact]
         public void TestThatGroupContainsOnlyLayerDetectsOnlySingleLayerThatIsNested()
         {
-            var doc = new Document(0, 0);
+            var doc = new Document(1, 1);
             doc.Layers.Add(new Layer("layer"));
             var guid = doc.Layers[0].LayerGuid;
             doc.LayerStructure.AddNewGroup("layer group", guid);
@@ -108,7 +108,7 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
         [Fact]
         public void TestThatCloneReturnsSameLayerStructure()
         {
-            Document doc = new(0, 0);
+            Document doc = new(1, 1);
             doc.Layers.Add(new("Test"));
             doc.Layers.Add(new("Test2"));
             LayerStructure structure = new(doc);
@@ -124,7 +124,7 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
         [Fact]
         public void TestThatGetGroupByGuidReturnsNullForNonExistingGroup()
         {
-            Document doc = new(0, 0);
+            Document doc = new(1, 1);
             doc.Layers.Add(new("Test"));
 
             Assert.Null(doc.LayerStructure.GetGroupByGuid(null));
@@ -134,7 +134,7 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
         [Fact]
         public void TestThatGetGroupByGuidReturnsGroupCorrectly()
         {
-            Document doc = new(0, 0);
+            Document doc = new(1, 1);
             doc.Layers.Add(new("Test"));
             var group = doc.LayerStructure.AddNewGroup("Test group", doc.Layers[0].LayerGuid);
 
@@ -144,7 +144,7 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
         [Fact]
         public void TestThatPreMoveReassignBoundsMakesNestedGroupEmptyAndRemovesItAndParent()
         {
-            Document doc = new(0, 0);
+            Document doc = new(1, 1);
             doc.Layers.Add(new("Test"));
             doc.LayerStructure.AddNewGroup("Test group", doc.Layers[0].LayerGuid);
             var group1 = doc.LayerStructure.AddNewGroup("Test group nested", doc.Layers[0].LayerGuid);
@@ -157,7 +157,7 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
         [Fact]
         public void TestThatPostMoveReassignBoundsAssignsNewLayerToGroup()
         {
-            Document doc = new(0, 0);
+            Document doc = new(1, 1);
             doc.Layers.Add(new("Test"));
             doc.LayerStructure.AddNewGroup("Test group", doc.Layers[0].LayerGuid);
             var group1 = doc.LayerStructure.AddNewGroup("Test group nested", doc.Layers[0].LayerGuid);
@@ -180,7 +180,7 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
         [Fact]
         public void TestThatAssignParentAssignsParent()
         {
-            Document doc = new(0, 0);
+            Document doc = new(1, 1);
             doc.Layers.Add(new Layer("Test"));
 
             var firstLayer = doc.Layers[0];
@@ -200,7 +200,7 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
         [Fact]
         public void TestThatAssignParentDeAssignsParentOnNull()
         {
-            Document doc = new(0, 0);
+            Document doc = new(1, 1);
             doc.Layers.Add(new Layer("Test"));
 
             var firstLayer = doc.Layers[0];
@@ -211,7 +211,7 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
 
             var layer = doc.Layers[^1];
 
-            doc.LayerStructure.AssignParent(layer.LayerGuid,  doc.LayerStructure.Groups[0].GroupGuid);
+            doc.LayerStructure.AssignParent(layer.LayerGuid, doc.LayerStructure.Groups[0].GroupGuid);
             doc.LayerStructure.AssignParent(layer.LayerGuid, null);
 
             Assert.Equal(firstLayer.LayerGuid, doc.LayerStructure.Groups[0].EndLayerGuid);
@@ -221,7 +221,7 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
         [Fact]
         public void TestThatGetGroupLayersReturnsAllLayersInGroup()
         {
-            Document doc = new(0, 0);
+            Document doc = new(1, 1);
             doc.Layers.Add(new Layer("Test"));
             doc.Layers.Add(new Layer("Test 1"));
             doc.Layers.Add(new Layer("Test 2"));
@@ -240,4 +240,4 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
             Assert.Contains(doc.Layers[2], layersInGroup);
         }
     }
-}
+}

+ 6 - 5
PixiEditorTests/ModelsTests/DataHoldersTests/SelectionTests.cs

@@ -1,9 +1,9 @@
-using System;
-using System.Collections.Generic;
-using PixiEditor.Helpers;
+using PixiEditor.Helpers;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.Enums;
 using PixiEditor.Models.Position;
+using System;
+using System.Collections.Generic;
 using Xunit;
 
 namespace PixiEditorTests.ModelsTests.DataHoldersTests
@@ -55,7 +55,8 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
             selection.Clear();
 
             Assert.Empty(selection.SelectedPoints);
-            Assert.Equal(0, selection.SelectionLayer.Width + selection.SelectionLayer.Height);
+            Assert.Equal(1, selection.SelectionLayer.Width);
+            Assert.Equal(1, selection.SelectionLayer.Height);
         }
 
         [Fact]
@@ -76,4 +77,4 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
             Assert.Equal(oldSelection, document.ActiveSelection.SelectedPoints);
         }
     }
-}
+}

+ 17 - 4
PixiEditorTests/ModelsTests/DataHoldersTests/SurfaceTests.cs

@@ -2,7 +2,7 @@ using PixiEditor.Models.DataHolders;
 using SkiaSharp;
 using Xunit;
 
-namespace PixiEditorSkiaRewrite
+namespace PixiEditorTests.ModelsTests.DataHoldersTests
 {
     public class SurfaceTests
     {
@@ -27,7 +27,7 @@ namespace PixiEditorSkiaRewrite
         public void TestSurfaceSRGBPixelManipulation()
         {
             using Surface surface = new Surface(128, 200);
-            surface.SkiaSurface.Canvas.Clear(SKExtendedColorTests.red);
+            surface.SkiaSurface.Canvas.Clear(SKColors.Red);
             surface.SkiaSurface.Canvas.DrawRect(new SKRect(10, 10, 70, 70), redPaint);
             surface.SetSRGBPixel(73, 21, greenColor);
             Assert.Equal(redColor, surface.GetSRGBPixel(14, 14));
@@ -79,17 +79,30 @@ namespace PixiEditorSkiaRewrite
         }
 
         [Fact]
-        public void TestSurfaceToSurface()
+        public void TestSurfaceToWriteableBitmap()
         {
             using Surface original = new Surface(30, 40);
             original.SkiaSurface.Canvas.Clear(redColor);
             original.SkiaSurface.Canvas.DrawRect(5, 5, 20, 20, greenPaint);
-            var bitmap = original.ToSurface();
+            var bitmap = original.ToWriteableBitmap();
             byte[] pixels = new byte[30 * 40 * 4];
             bitmap.CopyPixels(pixels, 30 * 4, 0);
             Assert.Equal(redColor, new SKColor(pixels[2], pixels[1], pixels[0], pixels[3]));
             int offset = (30 * 5 + 5) * 4;
             Assert.Equal(greenColor, new SKColor(pixels[2 + offset], pixels[1 + offset], pixels[0 + offset], pixels[3 + offset]));
         }
+
+        [Fact]
+        public void TestSurfaceFromWriteableBitmap()
+        {
+            using Surface original = new Surface(30, 30);
+            original.SkiaSurface.Canvas.Clear(SKColors.Transparent);
+            original.SkiaSurface.Canvas.DrawRect(5, 5, 20, 20, redPaint);
+            original.SkiaSurface.Canvas.DrawRect(10, 10, 20, 20, greenPaint);
+            using Surface fromWriteable = new Surface(original.ToWriteableBitmap());
+            Assert.Equal(original.GetSRGBPixel(0, 0), fromWriteable.GetSRGBPixel(0, 0));
+            Assert.Equal(original.GetSRGBPixel(6, 6), fromWriteable.GetSRGBPixel(6, 6));
+            Assert.Equal(original.GetSRGBPixel(15, 15), fromWriteable.GetSRGBPixel(15, 15));
+        }
     }
 }

+ 7 - 8
PixiEditorTests/ModelsTests/IO/ExporterTests.cs

@@ -1,11 +1,10 @@
-using System.IO;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
-using PixiEditor.Models.DataHolders;
+using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.IO;
 using PixiEditor.Models.Layers;
 using PixiEditor.Models.Position;
-using PixiEditorTests.ModelsTests.ColorsTests;
+using SkiaSharp;
+using System.IO;
+using System.Windows.Media.Imaging;
 using Xunit;
 
 namespace PixiEditorTests.ModelsTests.IO
@@ -31,9 +30,9 @@ namespace PixiEditorTests.ModelsTests.IO
             string filePath = "testFile.pixi";
 
             document.Layers.Add(new Layer("layer1"));
-            document.Layers[0].SetPixel(new Coordinates(1, 1), ExtendedColorTests.white);
+            document.Layers[0].SetPixel(new Coordinates(1, 1), SKColors.White);
 
-            document.Swatches.Add(ExtendedColorTests.white);
+            document.Swatches.Add(SKColors.White);
 
             Exporter.SaveAsEditableFile(document, filePath);
 
@@ -42,4 +41,4 @@ namespace PixiEditorTests.ModelsTests.IO
             File.Delete(filePath);
         }
     }
-}
+}

+ 2 - 5
PixiEditorTests/ModelsTests/IO/ImporterTests.cs

@@ -1,12 +1,9 @@
 using PixiEditor.Exceptions;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.IO;
-using PixiEditorTests.ModelsTests.ColorsTests;
 using SkiaSharp;
 using System;
 using System.IO;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
 using Xunit;
 
 namespace PixiEditorTests.ModelsTests.IO
@@ -37,7 +34,7 @@ namespace PixiEditorTests.ModelsTests.IO
         [Fact]
         public void TestThatImportImageImportsImage()
         {
-            SKColor color = new SKColor(255, 255, 0, 0);
+            SKColor color = new SKColor(255, 0, 0, 255);
             Surface image = Importer.ImportSurface(testImagePath);
 
             Assert.NotNull(image);
@@ -79,7 +76,7 @@ namespace PixiEditorTests.ModelsTests.IO
         public void TestSaveAndLoadGZippedBytes()
         {
             using Surface original = new Surface(123, 456);
-            original.SkiaSurface.Canvas.Clear(ExtendedColorTests.red);
+            original.SkiaSurface.Canvas.Clear(SKColors.Red);
             using SKPaint paint = new SKPaint();
             paint.BlendMode = SKBlendMode.Src;
             paint.Color = new SKColor(128, 64, 32, 16);

+ 22 - 45
PixiEditorTests/ModelsTests/ImageManipulationTests/BitmapUtilsTests.cs

@@ -1,40 +1,17 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
-using PixiEditor.Models.DataHolders;
+using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.ImageManipulation;
 using PixiEditor.Models.Layers;
 using PixiEditor.Models.Position;
-using PixiEditorTests.ModelsTests.ColorsTests;
+using SkiaSharp;
+using System;
+using System.Collections.Generic;
+using System.Linq;
 using Xunit;
 
 namespace PixiEditorTests.ModelsTests.ImageManipulationTests
 {
     public class BitmapUtilsTests
     {
-        [Fact]
-        public void TestBytesToSurface()
-        {
-            int width = 10;
-            int height = 10;
-            Coordinates[] coloredPoints = { new Coordinates(0, 0), new Coordinates(3, 6), new Coordinates(9, 9) };
-            Surface bmp = BitmapFactory.New(width, height);
-            for (int i = 0; i < coloredPoints.Length; i++)
-            {
-                bmp.SetPixel(coloredPoints[i].X, coloredPoints[i].Y, ExtendedColorTests.green);
-            }
-
-            byte[] byteArray = bmp.ToByteArray();
-
-            Surface convertedBitmap = BitmapUtils.BytesToSurface(width, height, byteArray);
-
-            for (int i = 0; i < coloredPoints.Length; i++)
-            {
-                Assert.Equal(ExtendedColorTests.green, convertedBitmap.GetPixel(coloredPoints[i].X, coloredPoints[i].Y));
-            }
-        }
 
         [Fact]
         public void TestThatCombineLayersReturnsCorrectBitmap()
@@ -42,14 +19,14 @@ namespace PixiEditorTests.ModelsTests.ImageManipulationTests
             Coordinates[] cords = { new Coordinates(0, 0), new Coordinates(1, 1) };
             Layer[] layers = { new Layer("test", 2, 2), new Layer("test2", 2, 2) };
 
-            layers[0].SetPixels(BitmapPixelChanges.FromSingleColoredArray(new[] { cords[0] }, ExtendedColorTests.green));
+            layers[0].SetPixels(BitmapPixelChanges.FromSingleColoredArray(new[] { cords[0] }, SKColors.Lime));
 
-            layers[1].SetPixels(BitmapPixelChanges.FromSingleColoredArray(new[] { cords[1] }, ExtendedColorTests.red));
+            layers[1].SetPixels(BitmapPixelChanges.FromSingleColoredArray(new[] { cords[1] }, SKColors.Red));
 
             Surface outputBitmap = BitmapUtils.CombineLayers(2, 2, layers);
 
-            Assert.Equal(ExtendedColorTests.green, outputBitmap.GetPixel(0, 0));
-            Assert.Equal(ExtendedColorTests.red, outputBitmap.GetPixel(1, 1));
+            Assert.Equal(SKColors.Lime, outputBitmap.GetSRGBPixel(0, 0));
+            Assert.Equal(SKColors.Red, outputBitmap.GetSRGBPixel(1, 1));
         }
 
         [Fact]
@@ -58,13 +35,13 @@ namespace PixiEditorTests.ModelsTests.ImageManipulationTests
             Coordinates[] cords = { new Coordinates(0, 0) };
             Layer[] layers = { new Layer("test", 2, 2), new Layer("test2", 2, 2) };
 
-            layers[0].SetPixels(BitmapPixelChanges.FromSingleColoredArray(cords, ExtendedColorTests.green));
+            layers[0].SetPixels(BitmapPixelChanges.FromSingleColoredArray(cords, SKColors.Lime));
 
-            layers[1].SetPixels(BitmapPixelChanges.FromSingleColoredArray(cords, ExtendedColorTests.red));
+            layers[1].SetPixels(BitmapPixelChanges.FromSingleColoredArray(cords, SKColors.Red));
 
             Surface outputBitmap = BitmapUtils.CombineLayers(2, 2, layers);
 
-            Assert.Equal(ExtendedColorTests.red, outputBitmap.GetSRGBPixel(0, 0));
+            Assert.Equal(SKColors.Red, outputBitmap.GetSRGBPixel(0, 0));
         }
 
         [Fact]
@@ -77,26 +54,26 @@ namespace PixiEditorTests.ModelsTests.ImageManipulationTests
             };
             Layer[] layers = { new Layer("test", 2, 2), new Layer("test2", 2, 2) };
 
-            layers[0].SetPixels(BitmapPixelChanges.FromSingleColoredArray(new[] { cords[0] }, ExtendedColorTests.green));
-            layers[1].SetPixels(BitmapPixelChanges.FromSingleColoredArray(new[] { cords[1] }, ExtendedColorTests.red));
+            layers[0].SetPixels(BitmapPixelChanges.FromSingleColoredArray(new[] { cords[0] }, SKColors.Lime));
+            layers[1].SetPixels(BitmapPixelChanges.FromSingleColoredArray(new[] { cords[1] }, SKColors.Red));
 
-            Dictionary<Guid, Color[]> output = BitmapUtils.GetPixelsForSelection(layers, cords);
+            Dictionary<Guid, SKColor[]> output = BitmapUtils.GetPixelsForSelection(layers, cords);
 
-            List<Color> colors = new List<Color>();
+            List<SKColor> colors = new List<SKColor>();
 
-            foreach (KeyValuePair<Guid, Color[]> layerColor in output.ToArray())
+            foreach (KeyValuePair<Guid, SKColor[]> layerColor in output.ToArray())
             {
-                foreach (Color color in layerColor.Value)
+                foreach (SKColor color in layerColor.Value)
                 {
                     colors.Add(color);
                 }
             }
 
-            Assert.Single(colors.Where(x => x == ExtendedColorTests.green));
-            Assert.Single(colors.Where(x => x == ExtendedColorTests.red));
-            Assert.Equal(6, colors.Count(x => x.A == 0)); // 6 because layer is 4 pixels,
+            Assert.Single(colors.Where(x => x == SKColors.Lime));
+            Assert.Single(colors.Where(x => x == SKColors.Red));
+            Assert.Equal(6, colors.Count(x => x.Alpha == 0)); // 6 because layer is 4 pixels,
 
             // 2 * 4 = 8, 2 other color pixels, so 8 - 2 = 6
         }
     }
-}
+}

+ 13 - 15
PixiEditorTests/ModelsTests/LayersTests/LayerTests.cs

@@ -1,9 +1,7 @@
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
-using PixiEditor.Models.DataHolders;
+using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.Layers;
 using PixiEditor.Models.Position;
-using PixiEditorTests.ModelsTests.ColorsTests;
+using SkiaSharp;
 using Xunit;
 
 namespace PixiEditorTests.ModelsTests.LayersTests
@@ -16,8 +14,8 @@ namespace PixiEditorTests.ModelsTests.LayersTests
             Layer layer = new Layer("layer");
 
             Assert.Equal("layer", layer.Name);
-            Assert.Equal(0, layer.Width);
-            Assert.Equal(0, layer.Height);
+            Assert.Equal(1, layer.Width);
+            Assert.Equal(1, layer.Height);
             Assert.Equal(1, layer.LayerBitmap.Width);
             Assert.Equal(1, layer.LayerBitmap.Height);
         }
@@ -65,9 +63,9 @@ namespace PixiEditorTests.ModelsTests.LayersTests
 
             Layer clone = layer.Clone();
 
-            clone.LayerBitmap.SetSRGBPixel(0, 0, ExtendedColorTests.green); // Actually we are checking if modifying clone bitmap does not affect original
+            clone.LayerBitmap.SetSRGBPixel(0, 0, SKColors.Lime); // Actually we are checking if modifying clone bitmap does not affect original
 
-            Assert.NotEqual(ExtendedColorTests.green, layer.GetPixel(0, 0));
+            Assert.NotEqual(SKColors.Lime, layer.GetPixel(0, 0));
         }
 
         [Fact]
@@ -75,7 +73,7 @@ namespace PixiEditorTests.ModelsTests.LayersTests
         {
             Layer layer = new Layer("layer", 1, 1);
 
-            layer.SetPixel(new Coordinates(0, 0), ExtendedColorTests.black);
+            layer.SetPixel(new Coordinates(0, 0), SKColors.Black);
 
             layer.Resize(2, 2, 2, 2);
 
@@ -89,7 +87,7 @@ namespace PixiEditorTests.ModelsTests.LayersTests
             {
                 for (int x = 0; x < layer.Width; x++)
                 {
-                    Assert.Equal(ExtendedColorTests.black, layer.GetPixel(x, y));
+                    Assert.Equal(SKColors.Black, layer.GetPixel(x, y));
                 }
             }
         }
@@ -109,11 +107,11 @@ namespace PixiEditorTests.ModelsTests.LayersTests
 
             Layer layer = new Layer("layer");
 
-            layer.SetPixels(BitmapPixelChanges.FromSingleColoredArray(pixels, ExtendedColorTests.green));
+            layer.SetPixels(BitmapPixelChanges.FromSingleColoredArray(pixels, SKColors.Lime));
 
             for (int i = 0; i < pixels.Length; i++)
             {
-                Assert.Equal(ExtendedColorTests.green, layer.GetPixelWithOffset(pixels[i].X, pixels[i].Y));
+                Assert.Equal(SKColors.Lime, layer.GetPixelWithOffset(pixels[i].X, pixels[i].Y));
             }
         }
 
@@ -121,13 +119,13 @@ namespace PixiEditorTests.ModelsTests.LayersTests
         public void TestThatClipCanvasResizesBitmapCorrectly()
         {
             Layer layer = new Layer("layer", 10, 10);
-            layer.SetPixel(new Coordinates(4, 4), ExtendedColorTests.blue);
+            layer.SetPixel(new Coordinates(4, 4), SKColors.Blue);
 
             layer.ClipCanvas();
 
             Assert.Equal(1, layer.Width);
             Assert.Equal(1, layer.Height);
-            Assert.Equal(ExtendedColorTests.blue, layer.GetPixel(0, 0));
+            Assert.Equal(SKColors.Blue, layer.GetPixel(0, 0));
         }
     }
-}
+}

+ 5 - 6
PixiEditorTests/ModelsTests/ToolsTests/BrightnessToolTests.cs

@@ -1,8 +1,7 @@
-using System.Windows.Media;
-using PixiEditor.Models.Layers;
+using PixiEditor.Models.Layers;
 using PixiEditor.Models.Position;
 using PixiEditor.Models.Tools.Tools;
-using PixiEditorTests.ModelsTests.ColorsTests;
+using SkiaSharp;
 using Xunit;
 
 namespace PixiEditorTests.ModelsTests.ToolsTests
@@ -17,12 +16,12 @@ namespace PixiEditorTests.ModelsTests.ToolsTests
         // If correction factor is negative, testing color will be white, otherwise black
         public void TestThatBrightnessToolChangesPixelBrightness(float correctionFactor, byte expectedR, byte expectedG, byte expectedB)
         {
-            Color expectedColor = Color.FromRgb(expectedR, expectedG, expectedB);
+            SKColor expectedColor = new SKColor(expectedR, expectedG, expectedB);
 
             BrightnessTool tool = new BrightnessTool();
 
             Layer layer = new Layer("test", 1, 1);
-            layer.SetPixel(new Coordinates(0, 0), correctionFactor < 0 ? ExtendedColorTests.white : ExtendedColorTests.black);
+            layer.SetPixel(new Coordinates(0, 0), correctionFactor < 0 ? SKColors.White : SKColors.Black);
 
             PixiEditor.Models.DataHolders.BitmapPixelChanges changes = tool.ChangeBrightness(layer, new Coordinates(0, 0), 1, correctionFactor);
             layer.SetPixels(changes);
@@ -30,4 +29,4 @@ namespace PixiEditorTests.ModelsTests.ToolsTests
             Assert.Equal(expectedColor, layer.GetPixel(0, 0));
         }
     }
-}
+}

+ 5 - 5
PixiEditorTests/ModelsTests/ToolsTests/PenToolTests.cs

@@ -1,7 +1,7 @@
 using PixiEditor.Models.Position;
 using PixiEditor.Models.Tools.Tools;
 using PixiEditorTests.HelpersTests;
-using PixiEditorTests.ModelsTests.ColorsTests;
+using SkiaSharp;
 using Xunit;
 
 namespace PixiEditorTests.ModelsTests.ToolsTests
@@ -19,11 +19,11 @@ namespace PixiEditorTests.ModelsTests.ToolsTests
             Coordinates end2 = new Coordinates(1, 0);
             Coordinates start2 = new Coordinates(1, 1);
 
-            pen.Draw(start, end, ExtendedColorTests.black, 1, true);
-            pen.Draw(end, end2, ExtendedColorTests.black, 1, true);
-            var points = pen.Draw(end2, start2, ExtendedColorTests.black, 1, true);
+            pen.Draw(start, end, SKColors.Black, 1, true);
+            pen.Draw(end, end2, SKColors.Black, 1, true);
+            var points = pen.Draw(end2, start2, SKColors.Black, 1, true);
 
             Assert.Contains(points.ChangedPixels, x => x.Value.Alpha == 0);
         }
     }
-}
+}

+ 10 - 16
PixiEditorTests/ModelsTests/UndoTests/StorageBasedChangeTests.cs

@@ -1,18 +1,12 @@
-using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
-using PixiEditor.Models.Controllers;
+using PixiEditor.Models.Controllers;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.Layers;
 using PixiEditor.Models.Undo;
-using PixiEditorTests.ModelsTests.ColorsTests;
 using PixiEditorTests.ModelsTests.LayersTests;
+using SkiaSharp;
+using System;
+using System.Collections.ObjectModel;
+using System.IO;
 using Xunit;
 
 namespace PixiEditorTests.ModelsTests.UndoTests
@@ -32,10 +26,10 @@ namespace PixiEditorTests.ModelsTests.UndoTests
         public Document GenerateTestDocument()
         {
             Document testDocument = new Document(10, 10);
-            using Surface testBitmap = new Surface(10, 10);
-            using Surface testBitmap2 = new Surface(5, 8);
-            testBitmap.SetSRGBPixel(0, 0, ExtendedColorTests.black);
-            testBitmap2.SetSRGBPixel(4, 4, ExtendedColorTests.blue);
+            Surface testBitmap = new Surface(10, 10);
+            Surface testBitmap2 = new Surface(5, 8);
+            testBitmap.SetSRGBPixel(0, 0, SKColors.Black);
+            testBitmap2.SetSRGBPixel(4, 4, SKColors.Blue);
             Random random = new Random();
             testDocument.Layers = new ObservableCollection<Layer>()
             {
@@ -167,4 +161,4 @@ namespace PixiEditorTests.ModelsTests.UndoTests
             Assert.True(redoInvoked);
         }
     }
-}
+}

+ 9 - 10
PixiEditorTests/ViewModelsTests/ViewModelMainTests.cs

@@ -3,10 +3,9 @@ using PixiEditor.Models.Position;
 using PixiEditor.Models.Tools.Tools;
 using PixiEditor.ViewModels;
 using PixiEditorTests.HelpersTests;
-using PixiEditorTests.ModelsTests.ColorsTests;
+using SkiaSharp;
 using System.IO;
 using System.Windows.Input;
-using System.Windows.Media;
 using Xunit;
 
 namespace PixiEditorTests.ViewModelsTests
@@ -31,13 +30,13 @@ namespace PixiEditorTests.ViewModelsTests
         {
             ViewModelMain viewModel = ViewModelHelper.MockedViewModelMain();
 
-            viewModel.ColorsSubViewModel.PrimaryColor = ExtendedColorTests.black;
-            viewModel.ColorsSubViewModel.SecondaryColor = ExtendedColorTests.white;
+            viewModel.ColorsSubViewModel.PrimaryColor = SKColors.Black;
+            viewModel.ColorsSubViewModel.SecondaryColor = SKColors.White;
 
             viewModel.ColorsSubViewModel.SwapColorsCommand.Execute(null);
 
-            Assert.Equal(ExtendedColorTests.white, viewModel.ColorsSubViewModel.PrimaryColor);
-            Assert.Equal(ExtendedColorTests.black, viewModel.ColorsSubViewModel.SecondaryColor);
+            Assert.Equal(SKColors.White, viewModel.ColorsSubViewModel.PrimaryColor);
+            Assert.Equal(SKColors.Black, viewModel.ColorsSubViewModel.SecondaryColor);
         }
 
         [StaFact]
@@ -131,11 +130,11 @@ namespace PixiEditorTests.ViewModelsTests
             ViewModelMain viewModel = ViewModelHelper.MockedViewModelMain();
             viewModel.BitmapManager.ActiveDocument = new Document(1, 1);
 
-            viewModel.ColorsSubViewModel.AddSwatch(ExtendedColorTests.green);
-            viewModel.ColorsSubViewModel.AddSwatch(ExtendedColorTests.green);
+            viewModel.ColorsSubViewModel.AddSwatch(SKColors.Lime);
+            viewModel.ColorsSubViewModel.AddSwatch(SKColors.Lime);
 
             Assert.Single(viewModel.BitmapManager.ActiveDocument.Swatches);
-            Assert.Equal(ExtendedColorTests.green, viewModel.BitmapManager.ActiveDocument.Swatches[0]);
+            Assert.Equal(SKColors.Lime, viewModel.BitmapManager.ActiveDocument.Swatches[0]);
         }
 
         [StaTheory]
@@ -171,4 +170,4 @@ namespace PixiEditorTests.ViewModelsTests
             Assert.True(viewModel.DocumentIsNotNull(null));
         }
     }
-}
+}