Browse Source

Pixel-perfect wip

flabbet 3 years ago
parent
commit
a421e72379
2 changed files with 128 additions and 21 deletions
  1. 94 2
      PixiEditor/Models/Tools/Tools/LineTool.cs
  2. 34 19
      PixiEditor/Models/Tools/Tools/PenTool.cs

+ 94 - 2
PixiEditor/Models/Tools/Tools/LineTool.cs

@@ -16,6 +16,97 @@ namespace PixiEditor.Models.Tools.Tools
         private List<Coordinates> linePoints = new List<Coordinates>();
         private List<Coordinates> linePoints = new List<Coordinates>();
         private SKPaint paint = new SKPaint() { Style = SKPaintStyle.Stroke };
         private SKPaint paint = new SKPaint() { Style = SKPaintStyle.Stroke };
 
 
+        public static List<Coordinates> GetBresenhamLine(Coordinates start, Coordinates end)
+        {
+            int x1 = start.X;
+            int x2 = end.X;
+            int y1 = start.Y;
+            int y2 = end.Y;
+
+            List<Coordinates> coordinates = new List<Coordinates>();
+            if (x1 == x2 && y1 == y2)
+            {
+                coordinates.Add(start);
+                return coordinates;
+            }
+
+            int d, dx, dy, ai, bi, xi, yi;
+            int x = x1, y = y1;
+
+            if (x1 < x2)
+            {
+                xi = 1;
+                dx = x2 - x1;
+            }
+            else
+            {
+                xi = -1;
+                dx = x1 - x2;
+            }
+
+            if (y1 < y2)
+            {
+                yi = 1;
+                dy = y2 - y1;
+            }
+            else
+            {
+                yi = -1;
+                dy = y1 - y2;
+            }
+
+            coordinates.Add(new Coordinates(x, y));
+
+            if (dx > dy)
+            {
+                ai = (dy - dx) * 2;
+                bi = dy * 2;
+                d = bi - dx;
+
+                while (x != x2)
+                {
+                    if (d >= 0)
+                    {
+                        x += xi;
+                        y += yi;
+                        d += ai;
+                    }
+                    else
+                    {
+                        d += bi;
+                        x += xi;
+                    }
+
+                    coordinates.Add(new Coordinates(x, y));
+                }
+            }
+            else
+            {
+                ai = (dx - dy) * 2;
+                bi = dx * 2;
+                d = bi - dy;
+
+                while (y != y2)
+                {
+                    if (d >= 0)
+                    {
+                        x += xi;
+                        y += yi;
+                        d += ai;
+                    }
+                    else
+                    {
+                        d += bi;
+                        y += yi;
+                    }
+
+                    coordinates.Add(new Coordinates(x, y));
+                }
+            }
+
+            return coordinates;
+        }
+
         public LineTool()
         public LineTool()
         {
         {
             ActionDisplay = "Click and move to draw a line. Hold Shift to draw an even one.";
             ActionDisplay = "Click and move to draw a line. Hold Shift to draw an even one.";
@@ -82,7 +173,7 @@ namespace PixiEditor.Models.Tools.Tools
 
 
             if (thickness == 1)
             if (thickness == 1)
             {
             {
-                BresenhamLine(layer, x, y, x1, y1, paint);
+                DrawBresenhamLine(layer, x, y, x1, y1, paint);
             }
             }
             else
             else
             {
             {
@@ -92,11 +183,12 @@ namespace PixiEditor.Models.Tools.Tools
             layer.InvokeLayerBitmapChange(dirtyRect);
             layer.InvokeLayerBitmapChange(dirtyRect);
         }
         }
 
 
-        private void BresenhamLine(Layer layer, int x1, int y1, int x2, int y2, SKPaint paint)
+        private void DrawBresenhamLine(Layer layer, int x1, int y1, int x2, int y2, SKPaint paint)
         {
         {
             if (x1 == x2 && y1 == y2)
             if (x1 == x2 && y1 == y2)
             {
             {
                 layer.LayerBitmap.SkiaSurface.Canvas.DrawPoint(x1, y1, paint);
                 layer.LayerBitmap.SkiaSurface.Canvas.DrawPoint(x1, y1, paint);
+                return;
             }
             }
 
 
             int d, dx, dy, ai, bi, xi, yi;
             int d, dx, dy, ai, bi, xi, yi;

+ 34 - 19
PixiEditor/Models/Tools/Tools/PenTool.cs

@@ -19,6 +19,7 @@ namespace PixiEditor.Models.Tools.Tools
         private readonly BoolSetting pixelPerfectSetting;
         private readonly BoolSetting pixelPerfectSetting;
         private readonly List<Coordinates> confirmedPixels = new List<Coordinates>();
         private readonly List<Coordinates> confirmedPixels = new List<Coordinates>();
         private readonly LineTool lineTool;
         private readonly LineTool lineTool;
+        private SKPaint paint = new SKPaint() { Style = SKPaintStyle.Stroke };
         private Coordinates[] lastChangedPixels = new Coordinates[3];
         private Coordinates[] lastChangedPixels = new Coordinates[3];
         private byte changedPixelsindex;
         private byte changedPixelsindex;
 
 
@@ -69,44 +70,44 @@ namespace PixiEditor.Models.Tools.Tools
             Layer previewLayer = null,
             Layer previewLayer = null,
             SKBlendMode blendMode = SKBlendMode.SrcOver)
             SKBlendMode blendMode = SKBlendMode.SrcOver)
         {
         {
+
+            SKStrokeCap cap = toolSize == 1 ? SKStrokeCap.Square : SKStrokeCap.Round;
             if (!pixelPerfect)
             if (!pixelPerfect)
             {
             {
-                lineTool.DrawLine(layer, startingCoords, latestCords, color, toolSize, blendMode, SKStrokeCap.Square);
+                lineTool.DrawLine(layer, startingCoords, latestCords, color, toolSize, blendMode, cap);
                 return;
                 return;
             }
             }
 
 
             if (previewLayer != null && previewLayer.GetPixelWithOffset(latestCords.X, latestCords.Y).Alpha > 0)
             if (previewLayer != null && previewLayer.GetPixelWithOffset(latestCords.X, latestCords.Y).Alpha > 0)
             {
             {
-                //confirmedPixels.Add(latestCords);
+                confirmedPixels.Add(latestCords);
             }
             }
 
 
-            lineTool.DrawLine(layer, startingCoords, latestCords, color, 1, blendMode, SKStrokeCap.Square);
-            //SetPixelToCheck(latestPixels);
+            lineTool.DrawLine(layer, startingCoords, latestCords, color, toolSize, blendMode, cap);
+            SetPixelToCheck(LineTool.GetBresenhamLine(startingCoords, latestCords));
 
 
-            /*if (changedPixelsindex == 2)
+            if (changedPixelsindex == 2)
             {
             {
-                var changes = ApplyPixelPerfectToPixels(
+                byte alpha = ApplyPixelPerfectToPixels(
                     layer,
                     layer,
                     lastChangedPixels[0],
                     lastChangedPixels[0],
                     lastChangedPixels[1],
                     lastChangedPixels[1],
                     lastChangedPixels[2],
                     lastChangedPixels[2],
                     color,
                     color,
-                    toolSize);
+                    toolSize,
+                    paint);
 
 
-                MovePixelsToCheck(changes);
+                MovePixelsToCheck(alpha);
 
 
-                ThickenShape(layer, color, latestPixels, toolSize);
                 return;
                 return;
             }
             }
 
 
             changedPixelsindex += changedPixelsindex >= 2 ? (byte)0 : (byte)1;
             changedPixelsindex += changedPixelsindex >= 2 ? (byte)0 : (byte)1;
-
-            ThickenShape(layer, color, latestPixels, toolSize);*/
         }

         }

 

 

-        private void MovePixelsToCheck(BitmapPixelChanges changes)
+        private void MovePixelsToCheck(byte alpha)
         {
         {
-            if (changes.ChangedPixels[lastChangedPixels[1]].Alpha != 0)
+            if (alpha != 0)
             {
             {
                 lastChangedPixels[0] = lastChangedPixels[1];
                 lastChangedPixels[0] = lastChangedPixels[1];
                 lastChangedPixels[1] = lastChangedPixels[2];
                 lastChangedPixels[1] = lastChangedPixels[2];
@@ -131,16 +132,30 @@ namespace PixiEditor.Models.Tools.Tools
             }
             }
         }
         }
 
 
-        private BitmapPixelChanges ApplyPixelPerfectToPixels(Layer layer, Coordinates p1, Coordinates p2, Coordinates p3, SKColor color, int toolSize)
+        private byte ApplyPixelPerfectToPixels(Layer layer, Coordinates p1, Coordinates p2, Coordinates p3, SKColor color, int toolSize, SKPaint paint)
         {
         {
+            byte alpha = color.Alpha;
+            paint.StrokeWidth = toolSize;
             if (Math.Abs(p3.X - p1.X) == 1 && Math.Abs(p3.Y - p1.Y) == 1 && !confirmedPixels.Contains(p2))
             if (Math.Abs(p3.X - p1.X) == 1 && Math.Abs(p3.Y - p1.Y) == 1 && !confirmedPixels.Contains(p2))
             {
             {
-                ThickenShape(layer, color, new Coordinates[] { p1, p3 }, toolSize);

-                ThickenShape(layer, color, new[] { p2 }, toolSize);
+                paint.Color = SKColors.Transparent;
+                paint.BlendMode = SKBlendMode.Src;
+                layer.LayerBitmap.SkiaSurface.Canvas.DrawPoint(p2.X, p2.Y, paint);
+                paint.Color = color;
+                layer.LayerBitmap.SkiaSurface.Canvas.DrawPoint(p1.X, p1.Y, paint);
+                layer.LayerBitmap.SkiaSurface.Canvas.DrawPoint(p3.X, p3.Y, paint);
+
+                if (lastChangedPixels.Length > 1 && p2 == lastChangedPixels[1] /*Here might be a bug, I don't remember if it should be p2*/)
+                {
+                    alpha = 0;
+                }
             }
             }
-
-            ThickenShape(layer, color, new Coordinates[] { p2, p3 }.Distinct(), toolSize);
-            return BitmapPixelChanges.Empty;
+            else
+            {
+                layer.LayerBitmap.SkiaSurface.Canvas.DrawPoint(p2.X, p2.Y, paint);
+                layer.LayerBitmap.SkiaSurface.Canvas.DrawPoint(p3.X, p3.Y, paint);
+            }
+            return alpha;
         }
         }
 
 
         private void PixelPerfectSettingValueChanged(object sender, SettingValueChangedEventArgs<bool> e)
         private void PixelPerfectSettingValueChanged(object sender, SettingValueChangedEventArgs<bool> e)