Browse Source

Fix crash when drawing outside canvas

Equbuxu 3 years ago
parent
commit
307460ca03

+ 3 - 2
PixiEditor/Models/Controllers/BitmapOperationsUtility.cs

@@ -87,14 +87,15 @@ namespace PixiEditor.Models.Controllers
             var previewLayer = Manager.ActiveDocument.PreviewLayer;
             var activeLayer = Manager.ActiveLayer;
 
-            activeLayer.DynamicResizeAbsolute(previewLayer.OffsetX + previewLayer.Width, previewLayer.OffsetY + previewLayer.Height, previewLayer.OffsetX, previewLayer.OffsetY);
+            Int32Rect dirtyRect = new Int32Rect(previewLayer.OffsetX, previewLayer.OffsetY, previewLayer.Width, previewLayer.Height);
+            activeLayer.DynamicResizeAbsolute(dirtyRect);
             previewLayer.LayerBitmap.SkiaSurface.Draw(
                     activeLayer.LayerBitmap.SkiaSurface.Canvas,
                     previewLayer.OffsetX - activeLayer.OffsetX,
                     previewLayer.OffsetY - activeLayer.OffsetY,
                     BlendingPaint
                 );
-            Manager.ActiveLayer.InvokeLayerBitmapChange(new Int32Rect(previewLayer.OffsetX, previewLayer.OffsetY, previewLayer.Width, previewLayer.Height));
+            Manager.ActiveLayer.InvokeLayerBitmapChange(dirtyRect);
             // Don't forget about firing BitmapChanged
             BitmapChanged?.Invoke(this, null);
             Manager.ActiveDocument.PreviewLayer.Reset();

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

@@ -84,7 +84,7 @@ namespace PixiEditor.Models.DataHolders
                     break;
             }
 
-            SelectionLayer.DynamicResizeAbsolute(rect.X + rect.Width - 1, rect.Y + rect.Height - 1, rect.X, rect.Y);
+            SelectionLayer.DynamicResizeAbsolute(new Int32Rect(rect.X, rect.Y, rect.Width, rect.Height));
             if (isCirclular)
             {
                 float cx = rect.X + rect.Width / 2f;

+ 11 - 8
PixiEditor/Models/Layers/Layer.cs

@@ -426,19 +426,22 @@ namespace PixiEditor.Models.Layers
             }
         }
 
-        public void DynamicResizeAbsolute(int newMaxX, int newMaxY, int newMinX, int newMinY)
+        public void DynamicResizeAbsolute(Int32Rect newSize)
         {
-            if (newMinX < 0) newMinX = 0;
-            if (newMinY < 0) newMinY = 0;
-            if (newMaxX >= MaxWidth) newMaxX = MaxWidth - 1;
-            if (newMaxY >= MaxHeight) newMaxY = MaxHeight - 1;
-
+            newSize = newSize.Intersect(new Int32Rect(0, 0, MaxWidth, MaxHeight));
+            if (newSize.IsEmpty)
+                return;
             if (IsReset)
             {
-                Offset = new Thickness(newMinX, newMinY, 0, 0);
+                Offset = new Thickness(newSize.X, newSize.Y, 0, 0);
             }
 
-            DynamicResizeRelative(newMaxX - OffsetX, newMaxY - OffsetY, newMinX - OffsetX, newMinY - OffsetY);
+            int relX = newSize.X - OffsetX;
+            int relY = newSize.Y - OffsetY;
+            int maxX = relX + newSize.Width - 1;
+            int maxY = relY + newSize.Height - 1;
+
+            DynamicResizeRelative(maxX, maxY, relX, relY);
         }
 
         /// <summary>

+ 3 - 2
PixiEditor/Models/Tools/Tools/BrightnessTool.cs

@@ -82,7 +82,8 @@ namespace PixiEditor.Models.Tools.Tools
                 UpdateCircleCache(toolSize);
 
             int radius = (int)Math.Ceiling(toolSize / 2f);
-            layer.DynamicResizeAbsolute(coordinates.X + radius, coordinates.Y + radius, coordinates.X - radius, coordinates.Y - radius);
+            Int32Rect dirtyRect = new(coordinates.X - radius, coordinates.Y - radius, radius * 2, radius * 2);
+            layer.DynamicResizeAbsolute(dirtyRect);
 
             foreach (var pair in circleCache)
             {
@@ -108,7 +109,7 @@ namespace PixiEditor.Models.Tools.Tools
                     layer.LayerBitmap.SkiaSurface.Canvas.DrawPoint(x - layer.OffsetX, y - layer.OffsetY, newColor);
                 }
             }
-            layer.InvokeLayerBitmapChange(new(coordinates.X - radius, coordinates.Y - radius, radius * 2, radius * 2));
+            layer.InvokeLayerBitmapChange(dirtyRect);
         }
 
         public void UpdateCircleCache(int newCircleSize)

+ 1 - 1
PixiEditor/Models/Tools/Tools/CircleTool.cs

@@ -28,7 +28,7 @@ namespace PixiEditor.Models.Tools.Tools
                 corners.Coords1.Y - halfThickness,
                 corners.Coords2.X + halfThickness * 2 - corners.Coords1.X,
                 corners.Coords2.Y + halfThickness * 2 - corners.Coords1.Y);
-            layer.DynamicResizeAbsolute(dirtyRect.X + dirtyRect.Width - 1, dirtyRect.Y + dirtyRect.Height - 1, dirtyRect.X, dirtyRect.Y);
+            layer.DynamicResizeAbsolute(dirtyRect);
 
             using (SKPaint paint = new SKPaint())
             {

+ 4 - 0
PixiEditor/Models/Tools/Tools/ColorPickerTool.cs

@@ -32,6 +32,10 @@ namespace PixiEditor.Models.Tools.Tools
         public override void Use(List<Coordinates> coordinates)
         {
             var coords = coordinates.First();
+            var doc = _docProvider.GetSurface();
+            if (coords.X < 0 || coords.Y < 0 || coords.X >= doc.Width || coords.Y >= doc.Height)
+                return;
+
             ViewModelMain.Current.ColorsSubViewModel.PrimaryColor = GetColorAt(coords.X, coords.Y);
         }
 

+ 2 - 2
PixiEditor/Models/Tools/Tools/FloodFillTool.cs

@@ -26,7 +26,7 @@ namespace PixiEditor.Models.Tools.Tools
         {
             if (layer.IsReset)
             {
-                layer.DynamicResizeAbsolute(BitmapManager.ActiveDocument.Width, BitmapManager.ActiveDocument.Height, 0, 0);
+                layer.DynamicResizeAbsolute(new(0, 0, BitmapManager.ActiveDocument.Width, BitmapManager.ActiveDocument.Height));
                 layer.LayerBitmap.SkiaSurface.Canvas.Clear(color);
                 layer.InvokeLayerBitmapChange();
             }
@@ -93,7 +93,7 @@ namespace PixiEditor.Models.Tools.Tools
             }
             int lastCheckedPixelRight = fillXRight - 1;
 
-            layer.DynamicResizeAbsolute(lastCheckedPixelRight, coords.Y, lastCheckedPixelLeft, coords.Y);
+            layer.DynamicResizeAbsolute(new(lastCheckedPixelLeft, coords.Y, lastCheckedPixelRight - lastCheckedPixelLeft + 1, 1));
             int relativeY = coords.Y - layer.OffsetY;
             layer.LayerBitmap.SkiaSurface.Canvas.DrawLine(lastCheckedPixelLeft - layer.OffsetX, relativeY, lastCheckedPixelRight - layer.OffsetX + 1, relativeY, fillPaint);
             dirtyRect = dirtyRect.Expand(new Int32Rect(lastCheckedPixelLeft, coords.Y, lastCheckedPixelRight - lastCheckedPixelLeft + 1, 1));

+ 1 - 1
PixiEditor/Models/Tools/Tools/LineTool.cs

@@ -169,7 +169,7 @@ namespace PixiEditor.Models.Tools.Tools
                 Math.Max(y1, y) + thickness - dirtyY);
             if (AutomaticallyResizeCanvas)
             {
-                layer.DynamicResizeAbsolute(dirtyRect.X + dirtyRect.Width - 1, dirtyRect.Y + dirtyRect.Height - 1, dirtyRect.X, dirtyRect.Y);
+                layer.DynamicResizeAbsolute(dirtyRect);
             }
 
             x -= layer.OffsetX;

+ 7 - 5
PixiEditor/Models/Tools/Tools/MoveTool.cs

@@ -228,10 +228,11 @@ namespace PixiEditor.Models.Tools.Tools
 
             int newX = moveStartRect.X + dX;
             int newY = moveStartRect.Y + dY;
-            
-            layer.DynamicResizeAbsolute(newX + moveStartRect.Width, newY + moveStartRect.Height, newX, newY);
+
+            Int32Rect dirtyRect = new Int32Rect(newX, newY, moveStartRect.Width, moveStartRect.Height);
+            layer.DynamicResizeAbsolute(dirtyRect);
             previewLayerData.SkiaSurface.Draw(layer.LayerBitmap.SkiaSurface.Canvas, newX - layer.OffsetX, newY - layer.OffsetY, Surface.ReplacingPaint);
-            layer.InvokeLayerBitmapChange(new Int32Rect(newX, newY, moveStartRect.Width, moveStartRect.Height));
+            layer.InvokeLayerBitmapChange(dirtyRect);
         }
 
         public override void OnStoppedRecordingMouseUp(MouseEventArgs e)
@@ -254,9 +255,10 @@ namespace PixiEditor.Models.Tools.Tools
                 var layer = layers[count];
                 using SKImage snapshot = surface.SkiaSurface.Snapshot();
                 Coordinates position = new Coordinates(startPositions[count].X + delta.X, startPositions[count].Y + delta.Y);
-                layer.DynamicResizeAbsolute(position.X + surface.Width, position.Y + surface.Height, position.X, position.Y);
+                Int32Rect dirtyRect = new Int32Rect(position.X, position.Y, surface.Width, surface.Height);
+                layer.DynamicResizeAbsolute(dirtyRect);
                 layer.LayerBitmap.SkiaSurface.Canvas.DrawImage(snapshot, position.X - layer.OffsetX, position.Y - layer.OffsetY);
-                layer.InvokeLayerBitmapChange(new Int32Rect(position.X, position.Y, surface.Width, surface.Height));
+                layer.InvokeLayerBitmapChange(dirtyRect);
 
                 count++;
             }

+ 5 - 1
PixiEditor/Models/Tools/Tools/PenTool.cs

@@ -68,7 +68,11 @@ namespace PixiEditor.Models.Tools.Tools
             paint.Color = color;
             if (AutomaticallyResizeCanvas)
             {
-                layer.DynamicResizeAbsolute(coordinates.Max(x => x.X), coordinates.Max(x => x.Y), coordinates.Min(x => x.X), coordinates.Min(x => x.Y));
+                int maxX = coordinates.Max(x => x.X);
+                int maxY = coordinates.Max(x => x.Y);
+                int minX = coordinates.Min(x => x.X);
+                int minY = coordinates.Min(x => x.Y);
+                layer.DynamicResizeAbsolute(new(minX, minY, maxX - minX + 1, maxX - minX + 1));
             }
             Draw(
                 layer,

+ 1 - 1
PixiEditor/Models/Tools/Tools/RectangleTool.cs

@@ -59,7 +59,7 @@ namespace PixiEditor.Models.Tools.Tools
                 fixedCoordinates.Coords1.Y - halfThickness,
                 fixedCoordinates.Coords2.X + halfThickness * 2 - fixedCoordinates.Coords1.X,
                 fixedCoordinates.Coords2.Y + halfThickness * 2 - fixedCoordinates.Coords1.Y);
-            layer.DynamicResizeAbsolute(dirtyRect.X + dirtyRect.Width - 1, dirtyRect.Y + dirtyRect.Height - 1, dirtyRect.X, dirtyRect.Y);
+            layer.DynamicResizeAbsolute(dirtyRect);
 
             using (SKPaint paint = new SKPaint())
             {