Skip to content

Commit

Permalink
PenTool (without pixel-perfect mode) refactored
Browse files Browse the repository at this point in the history
  • Loading branch information
flabbet committed Oct 10, 2021
1 parent 03a5000 commit 0034798
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 187 deletions.
8 changes: 3 additions & 5 deletions PixiEditor/Models/Tools/Tools/FloodFill.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,25 +30,23 @@ public override void Use(Layer layer, List<Coordinates> coordinates, SKColor col
Trace.WriteLine(sw.ElapsedMilliseconds);
}

public BitmapPixelChanges LinearFill(Layer layer, Coordinates startingCoords, SKColor newColor)
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) ||
colorToReplace == newColor)
return BitmapPixelChanges.Empty;
return;

int width = BitmapManager.ActiveDocument.Width;
int height = BitmapManager.ActiveDocument.Height;
if (startingCoords.X < 0 || startingCoords.Y < 0 || startingCoords.X >= width || startingCoords.Y >= height)
return BitmapPixelChanges.Empty;
return;
var visited = new bool[width * height];

PerformLinearFill(layer, changedCoords, floodFillQueue, startingCoords, width, colorToReplace, visited);
PerformFloodFIll(layer, changedCoords, floodFillQueue, colorToReplace, width, height, visited);

return BitmapPixelChanges.FromSingleColoredArray(changedCoords, newColor);
}

private void PerformLinearFill(
Expand Down
181 changes: 6 additions & 175 deletions PixiEditor/Models/Tools/Tools/LineTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ public override void Use(Layer layer, List<Coordinates> coordinates, SKColor col
Coordinates start = coordinates[0];
Coordinates end = coordinates[^1];

DrawLine(layer, start, end, color, thickness);
}

public void DrawLine(Layer layer, Coordinates start, Coordinates end, SKColor color, int thickness, SKStrokeCap strokeCap = SKStrokeCap.Butt)
{
int x = start.X;
int y = start.Y;
int x1 = end.X;
Expand All @@ -73,185 +78,11 @@ public override void Use(Layer layer, List<Coordinates> coordinates, SKColor col
paint.StrokeWidth = thickness;
paint.Style = SKPaintStyle.Stroke;
paint.Color = color;
paint.StrokeCap = strokeCap;
layer.LayerBitmap.SkiaSurface.Canvas.DrawLine(x, y, x1, y1, paint);
}

layer.InvokeLayerBitmapChange(dirtyRect);
}

public List<Coordinates> CreateLine(Layer layer, SKColor color, Coordinates start, Coordinates end, int thickness)
{
return CreateLineFastest(layer, color, start, end, thickness);
}

private List<Coordinates> CreateLine(Layer layer, SKColor color, IEnumerable<Coordinates> coordinates, int thickness, CapType startCap, CapType endCap)
{
Coordinates startingCoordinates = coordinates.Last();
Coordinates latestCoordinates = coordinates.First();

return CreateLine(layer, color, startingCoordinates, latestCoordinates, thickness, startCap, endCap);
}

private List<Coordinates> CreateLine(Layer layer, SKColor color, Coordinates start, Coordinates end, int thickness, CapType startCap, CapType endCap)
{
if (thickness == 1)
{
return BresenhamLine(layer, color, start.X, start.Y, end.X, end.Y);
}

return GenerateLine(layer, color, start, end, thickness, startCap, endCap);
}

private List<Coordinates> CreateLineFastest(Layer layer, SKColor color, Coordinates start, Coordinates end, int thickness)
{
var line = BresenhamLine(layer, color, start.X, start.Y, end.X, end.Y);
if (thickness == 1)
{
return line;
}

ThickenShape(layer, color, line, thickness);
return line;
}

private List<Coordinates> GenerateLine(Layer layer, SKColor color, Coordinates start, Coordinates end, int thickness, CapType startCap, CapType endCap)
{
ApplyCap(layer, color, startCap, start, thickness);
if (start == end)
{
return new List<Coordinates>() { start };
}

var line = BresenhamLine(layer, color, start.X, start.Y, end.X, end.Y);

ApplyCap(layer, color, endCap, end, thickness);
if (line.Count() > 2)
{
ThickenShape(layer, color, line.Except(new[] { start, end }), thickness);
}

return line;
}

private void ApplyCap(Layer layer, SKColor color, CapType cap, Coordinates position, int thickness)
{
switch (cap)
{
case CapType.Round:
ApplyRoundCap(layer, color, position, thickness); // Round cap is not working very well, circle tool must be improved
break;

default:
ThickenShape(layer, color, position, thickness);
break;
}
}

/// <summary>
/// Gets points for rounded cap on specified position and thickness.
/// </summary>
/// <param name="position">Starting position of cap.</param>
/// <param name="thickness">Thickness of cap.</param>
private void ApplyRoundCap(Layer layer, SKColor color, Coordinates position, int thickness)
{
IEnumerable<Coordinates> rectangleCords = CoordinatesCalculator.RectangleToCoordinates(
CoordinatesCalculator.CalculateThicknessCenter(position, thickness));
circleTool.CreateEllipse(layer, color, rectangleCords.First(), rectangleCords.Last(), 1, true);
}

private List<Coordinates> BresenhamLine(Layer layer, SKColor color, int x1, int y1, int x2, int y2)
{
//using BitmapContext context = layer.LayerBitmap.GetBitmapContext();
linePoints.Clear();
Coordinates cords;
if (x1 == x2 && y1 == y2)
{
cords = new Coordinates(x1, y1);
layer.SetPixelWithOffset(cords, color);
linePoints.Add(cords);
}

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;
}

cords = new Coordinates(x, y);
layer.SetPixelWithOffset(cords, color);
linePoints.Add(cords);

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;
}

cords = new Coordinates(x, y);
layer.SetPixelWithOffset(cords, color);
linePoints.Add(cords);
}
}
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;
}

cords = new Coordinates(x, y);
layer.SetPixelWithOffset(cords, color);
linePoints.Add(cords);
}
}

return linePoints;
}
}
}
4 changes: 2 additions & 2 deletions PixiEditor/Models/Tools/Tools/MagicWandTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,13 @@ public override void OnRecordingLeftMouseDown(MouseEventArgs e)

Selection selection = BitmapManager.ActiveDocument.ActiveSelection;

selection.SetSelection(
/*selection.SetSelection(
floodFill.LinearFill(
layer,
new Coordinates((int)document.MouseXOnCanvas, (int)document.MouseYOnCanvas),
SKColors.White
).ChangedPixels.Keys,
selectionType);
selectionType);*/

SelectionHelpers.AddSelectionUndoStep(ViewModelMain.Current.BitmapManager.ActiveDocument, oldSelection, selectionType);
}
Expand Down
10 changes: 5 additions & 5 deletions PixiEditor/Models/Tools/Tools/PenTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public void Draw(Layer layer, Coordinates startingCoords, Coordinates latestCord
{
if (!pixelPerfect)
{
lineTool.CreateLine(layer, color, startingCoords, latestCords, toolSize);
lineTool.DrawLine(layer, startingCoords, latestCords, color, toolSize, SKStrokeCap.Square);
return;
}

Expand All @@ -77,10 +77,10 @@ public void Draw(Layer layer, Coordinates startingCoords, Coordinates latestCord
confirmedPixels.Add(latestCords);
}

var latestPixels = lineTool.CreateLine(layer, color, startingCoords, latestCords, 1);
SetPixelToCheck(latestPixels);
lineTool.DrawLine(layer, startingCoords, latestCords, color, 1, SKStrokeCap.Square);
//SetPixelToCheck(latestPixels);

if (changedPixelsindex == 2)
/*if (changedPixelsindex == 2)
{
var changes = ApplyPixelPerfectToPixels(
layer,
Expand All @@ -98,7 +98,7 @@ public void Draw(Layer layer, Coordinates startingCoords, Coordinates latestCord
changedPixelsindex += changedPixelsindex >= 2 ? (byte)0 : (byte)1;
ThickenShape(layer, color, latestPixels, toolSize);
ThickenShape(layer, color, latestPixels, toolSize);*/
}

private void MovePixelsToCheck(BitmapPixelChanges changes)
Expand Down

0 comments on commit 0034798

Please sign in to comment.