Browse Source

Update CircleTool.cs

Krzysztof Krysiński 3 years ago
parent
commit
e75352841f
1 changed files with 30 additions and 164 deletions
  1. 30 164
      PixiEditor/Models/Tools/Tools/CircleTool.cs

+ 30 - 164
PixiEditor/Models/Tools/Tools/CircleTool.cs

@@ -1,10 +1,12 @@
-using PixiEditor.Models.Layers;
+using PixiEditor.Helpers.Extensions;
+using PixiEditor.Models.Layers;
 using PixiEditor.Models.Position;
 using PixiEditor.Models.Tools.ToolSettings.Settings;
 using SkiaSharp;
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Windows;
 using System.Windows.Input;
 using System.Windows.Media;
 
@@ -38,180 +40,44 @@ namespace PixiEditor.Models.Tools.Tools
         public override void Use(Layer layer, List<Coordinates> coordinates, SKColor color)
         {
             int thickness = Toolbar.GetSetting<SizeSetting>("ToolSize").Value;
+            var hasFillColor = Toolbar.GetSetting<BoolSetting>("Fill").Value;
             DoubleCords fixedCoordinates = CalculateCoordinatesForShapeRotation(coordinates[^1], coordinates[0]);
-            var outline = CreateEllipse(layer, color, fixedCoordinates.Coords1, fixedCoordinates.Coords2, thickness);
 
-            if (Toolbar.GetSetting<BoolSetting>("Fill").Value)
+            int halfThickness = (int)Math.Ceiling(thickness / 2.0);
+            Int32Rect dirtyRect = new Int32Rect(
+                fixedCoordinates.Coords1.X - halfThickness,
+                fixedCoordinates.Coords1.Y - halfThickness,
+                fixedCoordinates.Coords2.X + halfThickness * 2 - fixedCoordinates.Coords1.X,
+                fixedCoordinates.Coords2.Y + halfThickness * 2 - fixedCoordinates.Coords1.Y);
+            Int32Rect curLayerRect = new(layer.OffsetX, layer.OffsetY, layer.Width, layer.Height);
+            Int32Rect expanded = dirtyRect.Expand(curLayerRect);
+            layer.DynamicResize(expanded.X + expanded.Width - 1, expanded.Y + expanded.Height - 1, expanded.X, expanded.Y);
+
+            using (SKPaint paint = new SKPaint())
             {
-                Color temp = Toolbar.GetSetting<ColorSetting>("FillColor").Value;
-                SKColor fillColor = new SKColor(temp.R, temp.G, temp.B, temp.A);
-                DrawEllipseFill(layer, fillColor, outline);
-            }
-        }
-
-        /// <summary>
-        ///     Draws ellipse for specified coordinates and thickness.
-        /// </summary>
-        /// <param name="startCoordinates">Top left coordinate of ellipse.</param>
-        /// <param name="endCoordinates">Bottom right coordinate of ellipse.</param>
-        /// <param name="thickness">Thickness of ellipse.</param>
-        /// <param name="filled">Should ellipse be filled.</param>
-        public void CreateEllipse(Layer layer, SKColor color, Coordinates startCoordinates, Coordinates endCoordinates, int thickness, bool filled)
-        {
-            IEnumerable<Coordinates> outline = CreateEllipse(layer, color, startCoordinates, endCoordinates, thickness);
-            if (filled)
-            {
-                DrawEllipseFill(layer, color, outline);
-            }
-        }
-
-        /// <summary>
-        ///     Calculates ellipse points for specified coordinates and thickness.
-        /// </summary>
-        /// <param name="startCoordinates">Top left coordinate of ellipse.</param>
-        /// <param name="endCoordinates">Bottom right coordinate of ellipse.</param>
-        /// <param name="thickness">Thickness of ellipse.</param>
-        public IEnumerable<Coordinates> CreateEllipse(Layer layer, SKColor color, Coordinates startCoordinates, Coordinates endCoordinates, int thickness)
-        {
-            double radiusX = (endCoordinates.X - startCoordinates.X) / 2.0;
-            double radiusY = (endCoordinates.Y - startCoordinates.Y) / 2.0;
-            double centerX = (startCoordinates.X + endCoordinates.X + 1) / 2.0;
-            double centerY = (startCoordinates.Y + endCoordinates.Y + 1) / 2.0;
-
-            IEnumerable<Coordinates> ellipse = GenerateMidpointEllipse(layer, color, radiusX, radiusY, centerX, centerY);
-            if (thickness > 1)
-            {
-                ThickenShape(layer, color, ellipse, thickness);
-            }
-
-            return ellipse;
-        }
-
-        public List<Coordinates> GenerateMidpointEllipse(Layer layer, SKColor color, double halfWidth, double halfHeight, double centerX, double centerY)
-        {
-            //using var ctx = layer.LayerBitmap.GetBitmapContext();
-
-            if (halfWidth < 1 || halfHeight < 1)
-            {
-                return DrawFallbackRectangle(layer, color, halfWidth, halfHeight, centerX, centerY);
-            }
-
-            // ellipse formula: halfHeight^2 * x^2 + halfWidth^2 * y^2 - halfHeight^2 * halfWidth^2 = 0
-
-            // Make sure we are always at the center of a pixel
-            double currentX = Math.Ceiling(centerX - 0.5) + 0.5;
-            double currentY = centerY + halfHeight;
-
-            List<Coordinates> outputCoordinates = new List<Coordinates>();
-
-            double currentSlope;
-
-            // from PI/2 to middle
-            do
-            {
-                outputCoordinates.AddRange(DrawRegionPoints(layer, color, currentX, centerX, currentY, centerY));
-
-                // calculate next pixel coords
-                currentX++;
-
-                if ((Math.Pow(halfHeight, 2) * Math.Pow(currentX - centerX, 2)) +
-                    (Math.Pow(halfWidth, 2) * Math.Pow(currentY - centerY - 0.5, 2)) -
-                    (Math.Pow(halfWidth, 2) * Math.Pow(halfHeight, 2)) >= 0)
-                {
-                    currentY--;
-                }
+                float radiusX = (fixedCoordinates.Coords2.X - fixedCoordinates.Coords1.X) / 2.0f;
+                float radiusY = (fixedCoordinates.Coords2.Y - fixedCoordinates.Coords1.Y) / 2.0f;
+                float centerX = (fixedCoordinates.Coords1.X + fixedCoordinates.Coords2.X + 1) / 2.0f;
+                float centerY = (fixedCoordinates.Coords1.Y + fixedCoordinates.Coords2.Y + 1) / 2.0f;
 
-                // calculate how far we've advanced
-                double derivativeX = 2 * Math.Pow(halfHeight, 2) * (currentX - centerX);
-                double derivativeY = 2 * Math.Pow(halfWidth, 2) * (currentY - centerY);
-                currentSlope = -(derivativeX / derivativeY);
-            }
-            while (currentSlope > -1 && currentY - centerY > 0.5);
-
-            // from middle to 0
-            while (currentY - centerY >= 0)
-            {
-                outputCoordinates.AddRange(DrawRegionPoints(layer, color, currentX, centerX, currentY, centerY));
-
-                currentY--;
-                if ((Math.Pow(halfHeight, 2) * Math.Pow(currentX - centerX + 0.5, 2)) +
-                    (Math.Pow(halfWidth, 2) * Math.Pow(currentY - centerY, 2)) -
-                    (Math.Pow(halfWidth, 2) * Math.Pow(halfHeight, 2)) < 0)
+                if (hasFillColor)
                 {
-                    currentX++;
-                }
-            }
-
-            return outputCoordinates;
-        }
+                    Color temp = Toolbar.GetSetting<ColorSetting>("FillColor").Value;
+                    SKColor fillColor = new SKColor(temp.R, temp.G, temp.B, temp.A);
 
-        public void DrawEllipseFill(Layer layer, SKColor color, IEnumerable<Coordinates> outlineCoordinates)
-        {
-            //using var ctx = layer.LayerBitmap.GetBitmapContext();
-
-            if (!outlineCoordinates.Any())
-            {
-                return;
-            }
-
-            int bottom = outlineCoordinates.Max(x => x.Y);
-            int top = outlineCoordinates.Min(x => x.Y);
-            for (int i = top + 1; i < bottom; i++)
-            {
-                IEnumerable<Coordinates> rowCords = outlineCoordinates.Where(x => x.Y == i);
-                int right = rowCords.Max(x => x.X);
-                int left = rowCords.Min(x => x.X);
-                for (int j = left + 1; j < right; j++)
-                {
-                    layer.SetPixel(new Coordinates(j, i), color);
+                    paint.Color = fillColor;
+                    paint.Style = SKPaintStyle.StrokeAndFill;
+                    layer.LayerBitmap.SkiaSurface.Canvas.DrawOval(centerX, centerY, radiusX, radiusY, paint);
                 }
-            }
-        }
-
-        private List<Coordinates> DrawFallbackRectangle(Layer layer, SKColor color, double halfWidth, double halfHeight, double centerX, double centerY)
-        {
-            //using var ctx = layer.LayerBitmap.GetBitmapContext();
-
-            List<Coordinates> coordinates = new List<Coordinates>();
-
-            for (double x = centerX - halfWidth; x <= centerX + halfWidth; x++)
-            {
-                var cords = new Coordinates((int)x, (int)(centerY - halfHeight));
-                coordinates.Add(cords);
-                layer.SetPixel(cords, color);
 
-                cords = new Coordinates((int)x, (int)(centerY + halfHeight));
-                coordinates.Add(cords);
-                layer.SetPixel(cords, color);
+                paint.Color = color;
+                paint.StrokeWidth = thickness;
+                paint.Style = SKPaintStyle.Stroke;
+                layer.LayerBitmap.SkiaSurface.Canvas.DrawOval(centerX, centerY, radiusX, radiusY, paint);
             }
 
-            for (double y = centerY - halfHeight + 1; y <= centerY + halfHeight - 1; y++)
-            {
-                var cords = new Coordinates((int)(centerX - halfWidth), (int)y);
-                coordinates.Add(cords);
-                layer.SetPixel(cords, color);
-
-                cords = new Coordinates((int)(centerX + halfWidth), (int)y);
-                coordinates.Add(cords);
-                layer.SetPixel(cords, color);
-            }
-
-            return coordinates;
-        }
-
-        private Coordinates[] DrawRegionPoints(Layer layer, SKColor color, double x, double xc, double y, double yc)
-        {
-            Coordinates[] outputCoordinates = new Coordinates[4];
-            outputCoordinates[0] = new Coordinates((int)Math.Floor(x), (int)Math.Floor(y));
-            layer.SetPixel(outputCoordinates[0], color);
-            outputCoordinates[1] = new Coordinates((int)Math.Floor(-(x - xc) + xc), (int)Math.Floor(y));
-            layer.SetPixel(outputCoordinates[1], color);
-            outputCoordinates[2] = new Coordinates((int)Math.Floor(x), (int)Math.Floor(-(y - yc) + yc));
-            layer.SetPixel(outputCoordinates[2], color);
-            outputCoordinates[3] = new Coordinates((int)Math.Floor(-(x - xc) + xc), (int)Math.Floor(-(y - yc) + yc));
-            layer.SetPixel(outputCoordinates[3], color);
+            layer.InvokeLayerBitmapChange(dirtyRect);
 
-            return outputCoordinates;
         }
     }
 }