|
@@ -1,19 +1,20 @@
|
|
|
-using PixiEditor.Models.Controllers;
|
|
|
-using PixiEditor.Models.DataHolders;
|
|
|
+using PixiEditor.Helpers.Extensions;
|
|
|
+using PixiEditor.Models.Controllers;
|
|
|
using PixiEditor.Models.Layers;
|
|
|
using PixiEditor.Models.Position;
|
|
|
using SkiaSharp;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Diagnostics;
|
|
|
+using System.Windows;
|
|
|
|
|
|
namespace PixiEditor.Models.Tools.Tools
|
|
|
{
|
|
|
- public class FloodFill : BitmapOperationTool
|
|
|
+ public class FloodFillTool : BitmapOperationTool
|
|
|
{
|
|
|
private BitmapManager BitmapManager { get; }
|
|
|
+ private SKPaint fillPaint = new SKPaint() { BlendMode = SKBlendMode.Src };
|
|
|
|
|
|
-
|
|
|
- public FloodFill(BitmapManager bitmapManager)
|
|
|
+ public FloodFillTool(BitmapManager bitmapManager)
|
|
|
{
|
|
|
ActionDisplay = "Press on an area to fill it.";
|
|
|
BitmapManager = bitmapManager;
|
|
@@ -32,7 +33,6 @@ namespace PixiEditor.Models.Tools.Tools
|
|
|
|
|
|
public void LinearFill(Layer layer, Coordinates startingCoords, SKColor newColor)
|
|
|
{
|
|
|
- List<Coordinates> changedCoords = new List<Coordinates>();
|
|
|
Queue<FloodFillRange> floodFillQueue = new Queue<FloodFillRange>();
|
|
|
SKColor colorToReplace = layer.GetPixelWithOffset(startingCoords.X, startingCoords.Y);
|
|
|
if ((colorToReplace.Alpha == 0 && newColor.Alpha == 0) ||
|
|
@@ -45,23 +45,25 @@ namespace PixiEditor.Models.Tools.Tools
|
|
|
return;
|
|
|
var visited = new bool[width * height];
|
|
|
|
|
|
- PerformLinearFill(layer, changedCoords, floodFillQueue, startingCoords, width, colorToReplace, visited);
|
|
|
- PerformFloodFIll(layer, changedCoords, floodFillQueue, colorToReplace, width, height, visited);
|
|
|
+ fillPaint.Color = newColor;
|
|
|
+
|
|
|
+ Int32Rect dirtyRect = new Int32Rect(startingCoords.X, startingCoords.Y, 1, 1);
|
|
|
+
|
|
|
+ PerformLinearFill(layer, floodFillQueue, startingCoords, width, colorToReplace, ref dirtyRect, visited);
|
|
|
+ PerformFloodFIll(layer, floodFillQueue, colorToReplace, ref dirtyRect, width, height, visited);
|
|
|
+
|
|
|
+ layer.InvokeLayerBitmapChange(dirtyRect);
|
|
|
}
|
|
|
|
|
|
private void PerformLinearFill(
|
|
|
- Layer layer,
|
|
|
- List<Coordinates> changedCoords, Queue<FloodFillRange> floodFillQueue,
|
|
|
- Coordinates coords, int width, SKColor colorToReplace, bool[] visited)
|
|
|
+ Layer layer, Queue<FloodFillRange> floodFillQueue,
|
|
|
+ Coordinates coords, int width, SKColor colorToReplace, ref Int32Rect dirtyRect, bool[] visited)
|
|
|
{
|
|
|
// Find the Left Edge of the Color Area
|
|
|
int fillXLeft = coords.X;
|
|
|
while (true)
|
|
|
{
|
|
|
- // Fill with the color
|
|
|
- changedCoords.Add(new Coordinates(fillXLeft, coords.Y));
|
|
|
-
|
|
|
- // Indicate that this pixel has already been checked and filled
|
|
|
+ // Indicate that this pixel has been checked
|
|
|
int pixelIndex = (coords.Y * width) + fillXLeft;
|
|
|
visited[pixelIndex] = true;
|
|
|
|
|
@@ -71,15 +73,12 @@ namespace PixiEditor.Models.Tools.Tools
|
|
|
if (fillXLeft < 0 || visited[pixelIndex - 1] || layer.GetPixelWithOffset(fillXLeft, coords.Y) != colorToReplace)
|
|
|
break;
|
|
|
}
|
|
|
- int lastFilledPixelLeft = fillXLeft + 1;
|
|
|
-
|
|
|
+ int lastCheckedPixelLeft = fillXLeft + 1;
|
|
|
|
|
|
// Find the Right Edge of the Color Area
|
|
|
int fillXRight = coords.X;
|
|
|
while (true)
|
|
|
{
|
|
|
- changedCoords.Add(new Coordinates(fillXRight, coords.Y));
|
|
|
-
|
|
|
int pixelIndex = (coords.Y * width) + fillXRight;
|
|
|
visited[pixelIndex] = true;
|
|
|
|
|
@@ -87,17 +86,20 @@ namespace PixiEditor.Models.Tools.Tools
|
|
|
if (fillXRight >= width || visited[pixelIndex + 1] || layer.GetPixelWithOffset(fillXRight, coords.Y) != colorToReplace)
|
|
|
break;
|
|
|
}
|
|
|
- int lastFilledPixelRight = fillXRight - 1;
|
|
|
+ int lastCheckedPixelRight = fillXRight - 1;
|
|
|
|
|
|
+ layer.DynamicResizeAbsolute(lastCheckedPixelRight, coords.Y, lastCheckedPixelLeft, coords.Y);
|
|
|
+ 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));
|
|
|
|
|
|
- FloodFillRange range = new FloodFillRange(lastFilledPixelLeft, lastFilledPixelRight, coords.Y);
|
|
|
+ FloodFillRange range = new FloodFillRange(lastCheckedPixelLeft, lastCheckedPixelRight, coords.Y);
|
|
|
floodFillQueue.Enqueue(range);
|
|
|
}
|
|
|
|
|
|
private void PerformFloodFIll(
|
|
|
- Layer layer,
|
|
|
- List<Coordinates> changedCords, Queue<FloodFillRange> floodFillQueue,
|
|
|
- SKColor colorToReplace, int width, int height, bool[] pixelsVisited)
|
|
|
+ Layer layer, Queue<FloodFillRange> floodFillQueue,
|
|
|
+ SKColor colorToReplace, ref Int32Rect dirtyRect, int width, int height, bool[] pixelsVisited)
|
|
|
{
|
|
|
while (floodFillQueue.Count > 0)
|
|
|
{
|
|
@@ -113,10 +115,10 @@ namespace PixiEditor.Models.Tools.Tools
|
|
|
//START LOOP UPWARDS
|
|
|
//if we're not above the top of the bitmap and the pixel above this one is within the color tolerance
|
|
|
if (range.Y > 0 && (!pixelsVisited[upPixelIndex]) && layer.GetPixelWithOffset(i, upY) == colorToReplace)
|
|
|
- PerformLinearFill(layer, changedCords, floodFillQueue, new Coordinates(i, upY), width, colorToReplace, pixelsVisited);
|
|
|
+ PerformLinearFill(layer, floodFillQueue, new Coordinates(i, upY), width, colorToReplace, ref dirtyRect, pixelsVisited);
|
|
|
//START LOOP DOWNWARDS
|
|
|
- if (range.Y < (height - 1) && (!pixelsVisited[downPixelxIndex]) && layer.GetPixel(i, downY) == colorToReplace)
|
|
|
- PerformLinearFill(layer, changedCords, floodFillQueue, new Coordinates(i, downY), width, colorToReplace, pixelsVisited);
|
|
|
+ if (range.Y < (height - 1) && (!pixelsVisited[downPixelxIndex]) && layer.GetPixelWithOffset(i, downY) == colorToReplace)
|
|
|
+ PerformLinearFill(layer, floodFillQueue, new Coordinates(i, downY), width, colorToReplace, ref dirtyRect, pixelsVisited);
|
|
|
downPixelxIndex++;
|
|
|
upPixelIndex++;
|
|
|
}
|