|
@@ -64,19 +64,13 @@ namespace PixiEditor.Models.Tools.Tools
|
|
|
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;
|
|
|
- paint.BlendMode = SKBlendMode.Src;
|
|
|
-
|
|
|
- paint.Color = color;
|
|
|
- paint.StrokeWidth = thickness;
|
|
|
- paint.Style = SKPaintStyle.Stroke;
|
|
|
- var outline = DrawEllipse(layer, color, centerX, centerY, radiusX, radiusY, thickness);
|
|
|
|
|
|
+ List<Coordinates> outline = GenerateMidpointEllipse(radiusX, radiusY, centerX, centerY);
|
|
|
if (hasFillColor)
|
|
|
{
|
|
|
- paint.Color = fillColor;
|
|
|
- paint.Style = SKPaintStyle.StrokeAndFill;
|
|
|
DrawEllipseFill(layer, fillColor, outline);
|
|
|
}
|
|
|
+ DrawEllipseOutline(layer, color, outline, thickness);
|
|
|
|
|
|
// An Idea, use Skia DrawOval for bigger sizes.
|
|
|
}
|
|
@@ -84,27 +78,59 @@ namespace PixiEditor.Models.Tools.Tools
|
|
|
layer.InvokeLayerBitmapChange(dirtyRect);
|
|
|
}
|
|
|
|
|
|
+ public static void DrawEllipseFill(Layer layer, SKColor color, List<Coordinates> outlineCoordinates)
|
|
|
+ {
|
|
|
+ if (!outlineCoordinates.Any())
|
|
|
+ return;
|
|
|
+
|
|
|
+ int bottom = outlineCoordinates.Max(x => x.Y);
|
|
|
+ int top = outlineCoordinates.Min(x => x.Y);
|
|
|
+
|
|
|
+ using SKPaint fillPaint = new();
|
|
|
+ fillPaint.Color = color;
|
|
|
+ fillPaint.BlendMode = SKBlendMode.Src;
|
|
|
+
|
|
|
+ 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);
|
|
|
+ layer.LayerBitmap.SkiaSurface.Canvas.DrawLine(left - layer.OffsetX, i - layer.OffsetY, right - layer.OffsetX, i - layer.OffsetY, fillPaint);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// Calculates ellipse points for specified coordinates and thickness.
|
|
|
/// </summary>
|
|
|
/// <param name="thickness">Thickness of ellipse.</param>
|
|
|
- public static IEnumerable<Coordinates> DrawEllipse(Layer layer, SKColor color, float centerX, float centerY, float radiusX, float radiusY, int thickness)
|
|
|
+ public static void DrawEllipseOutline(Layer layer, SKColor color, List<Coordinates> ellipse, int thickness)
|
|
|
{
|
|
|
-
|
|
|
- IEnumerable<Coordinates> ellipse = GenerateMidpointEllipse(layer, color, radiusX, radiusY, centerX, centerY);
|
|
|
- if (thickness > 1)
|
|
|
+ if (thickness == 1)
|
|
|
{
|
|
|
- ShapeTool.ThickenShape(layer, color, ellipse, thickness);
|
|
|
+ foreach (var coords in ellipse)
|
|
|
+ {
|
|
|
+ layer.LayerBitmap.SetSRGBPixel(coords.X - layer.OffsetX, coords.Y - layer.OffsetY, color);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ using SKPaint paint = new();
|
|
|
+ paint.Color = color;
|
|
|
+ paint.BlendMode = SKBlendMode.Src;
|
|
|
+ float offsetX = thickness % 2 == 1 ? layer.OffsetX - 0.5f : layer.OffsetX;
|
|
|
+ float offsetY = thickness % 2 == 1 ? layer.OffsetY - 0.5f : layer.OffsetY;
|
|
|
+ foreach (var coords in ellipse)
|
|
|
+ {
|
|
|
+ layer.LayerBitmap.SkiaSurface.Canvas.DrawCircle(coords.X - offsetX, coords.Y - offsetY, thickness / 2f, paint);
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
- return ellipse;
|
|
|
}
|
|
|
|
|
|
- public static List<Coordinates> GenerateMidpointEllipse(Layer layer, SKColor color, double halfWidth, double halfHeight, double centerX, double centerY)
|
|
|
+ public static List<Coordinates> GenerateMidpointEllipse(double halfWidth, double halfHeight, double centerX, double centerY)
|
|
|
{
|
|
|
if (halfWidth < 1 || halfHeight < 1)
|
|
|
{
|
|
|
- return DrawFallbackRectangle(layer, color, halfWidth, halfHeight, centerX, centerY);
|
|
|
+ return GenerateFallbackRectangle(halfWidth, halfHeight, centerX, centerY);
|
|
|
}
|
|
|
|
|
|
// ellipse formula: halfHeight^2 * x^2 + halfWidth^2 * y^2 - halfHeight^2 * halfWidth^2 = 0
|
|
@@ -120,7 +146,7 @@ namespace PixiEditor.Models.Tools.Tools
|
|
|
// from PI/2 to middle
|
|
|
do
|
|
|
{
|
|
|
- outputCoordinates.AddRange(DrawRegionPoints(layer, color, currentX, centerX, currentY, centerY));
|
|
|
+ AddRegionPoints(outputCoordinates, currentX, centerX, currentY, centerY);
|
|
|
|
|
|
// calculate next pixel coords
|
|
|
currentX++;
|
|
@@ -142,7 +168,7 @@ namespace PixiEditor.Models.Tools.Tools
|
|
|
// from middle to 0
|
|
|
while (currentY - centerY >= 0)
|
|
|
{
|
|
|
- outputCoordinates.AddRange(DrawRegionPoints(layer, color, currentX, centerX, currentY, centerY));
|
|
|
+ AddRegionPoints(outputCoordinates, currentX, centerX, currentY, centerY);
|
|
|
|
|
|
currentY--;
|
|
|
if ((Math.Pow(halfHeight, 2) * Math.Pow(currentX - centerX + 0.5, 2)) +
|
|
@@ -156,71 +182,31 @@ namespace PixiEditor.Models.Tools.Tools
|
|
|
return outputCoordinates;
|
|
|
}
|
|
|
|
|
|
- public static void DrawEllipseFill(Layer layer, SKColor color, IEnumerable<Coordinates> outlineCoordinates)
|
|
|
- {
|
|
|
- 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.LayerBitmap.SkiaSurface.Canvas.DrawPoint(new SKPoint(j - layer.OffsetX, i - layer.OffsetY), color);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private static List<Coordinates> DrawFallbackRectangle(Layer layer, SKColor color, double halfWidth, double halfHeight, double centerX, double centerY)
|
|
|
+ private static List<Coordinates> GenerateFallbackRectangle(double halfWidth, double halfHeight, double centerX, double centerY)
|
|
|
{
|
|
|
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.LayerBitmap.SkiaSurface.Canvas.DrawPoint(new SKPoint(cords.X - layer.OffsetX, cords.Y - layer.OffsetY), color);
|
|
|
-
|
|
|
- cords = new Coordinates((int)x, (int)(centerY + halfHeight));
|
|
|
- coordinates.Add(cords);
|
|
|
- layer.LayerBitmap.SkiaSurface.Canvas.DrawPoint(new SKPoint(cords.X - layer.OffsetX, cords.Y - layer.OffsetY), color);
|
|
|
-
|
|
|
+ coordinates.Add(new Coordinates((int)x, (int)(centerY - halfHeight)));
|
|
|
+ coordinates.Add(new Coordinates((int)x, (int)(centerY + halfHeight)));
|
|
|
}
|
|
|
|
|
|
for (double y = centerY - halfHeight + 1; y <= centerY + halfHeight - 1; y++)
|
|
|
{
|
|
|
- var cords = new Coordinates((int)(centerX - halfWidth), (int)y);
|
|
|
- coordinates.Add(cords);
|
|
|
- layer.LayerBitmap.SkiaSurface.Canvas.DrawPoint(new SKPoint(cords.X - layer.OffsetX, cords.Y - layer.OffsetY), color);
|
|
|
-
|
|
|
- cords = new Coordinates((int)(centerX + halfWidth), (int)y);
|
|
|
- coordinates.Add(cords);
|
|
|
- layer.LayerBitmap.SkiaSurface.Canvas.DrawPoint(new SKPoint(cords.X - layer.OffsetX, cords.Y - layer.OffsetY), color);
|
|
|
-
|
|
|
+ coordinates.Add(new Coordinates((int)(centerX - halfWidth), (int)y));
|
|
|
+ coordinates.Add(new Coordinates((int)(centerX + halfWidth), (int)y));
|
|
|
}
|
|
|
|
|
|
return coordinates;
|
|
|
}
|
|
|
|
|
|
- private static Coordinates[] DrawRegionPoints(Layer layer, SKColor color, double x, double xc, double y, double yc)
|
|
|
+ private static void AddRegionPoints(List<Coordinates> coordinates, 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.LayerBitmap.SkiaSurface.Canvas.DrawPoint(new SKPoint(outputCoordinates[0].X - layer.OffsetX, outputCoordinates[0].Y - layer.OffsetY), color);
|
|
|
- outputCoordinates[1] = new Coordinates((int)Math.Floor(-(x - xc) + xc), (int)Math.Floor(y));
|
|
|
- layer.LayerBitmap.SkiaSurface.Canvas.DrawPoint(new SKPoint(outputCoordinates[1].X - layer.OffsetX, outputCoordinates[1].Y - layer.OffsetY), color);
|
|
|
- outputCoordinates[2] = new Coordinates((int)Math.Floor(x), (int)Math.Floor(-(y - yc) + yc));
|
|
|
- layer.LayerBitmap.SkiaSurface.Canvas.DrawPoint(new SKPoint(outputCoordinates[2].X - layer.OffsetX, outputCoordinates[2].Y - layer.OffsetY), color);
|
|
|
- outputCoordinates[3] = new Coordinates((int)Math.Floor(-(x - xc) + xc), (int)Math.Floor(-(y - yc) + yc));
|
|
|
- layer.LayerBitmap.SkiaSurface.Canvas.DrawPoint(new SKPoint(outputCoordinates[3].X - layer.OffsetX, outputCoordinates[3].Y - layer.OffsetY), color);
|
|
|
-
|
|
|
- return outputCoordinates;
|
|
|
+ coordinates.Add(new Coordinates((int)Math.Floor(x), (int)Math.Floor(y)));
|
|
|
+ coordinates.Add(new Coordinates((int)Math.Floor(-(x - xc) + xc), (int)Math.Floor(y)));
|
|
|
+ coordinates.Add(new Coordinates((int)Math.Floor(x), (int)Math.Floor(-(y - yc) + yc)));
|
|
|
+ coordinates.Add(new Coordinates((int)Math.Floor(-(x - xc) + xc), (int)Math.Floor(-(y - yc) + yc)));
|
|
|
}
|
|
|
}
|
|
|
}
|