From a56287cb85899a5fc5455df870eeee264cabc3ee Mon Sep 17 00:00:00 2001 From: Scott Williams Date: Sun, 12 Jan 2020 14:46:23 +0000 Subject: [PATCH 1/2] remove all drawing except draw image --- ImageSharp.sln | 15 - appveyor.yml | 3 +- build.ps1 | 3 - .../Extensions/GraphicsOptionsExtensions.cs | 53 -- .../ImageSharp.Drawing.csproj | 24 - .../ImageSharp.Drawing.csproj.DotSettings | 2 - src/ImageSharp.Drawing/Primitives/Region.cs | 36 -- .../Primitives/ShapePath.cs | 24 - .../Primitives/ShapeRegion.cs | 64 --- .../Processing/BrushApplicator.cs | 117 ----- src/ImageSharp.Drawing/Processing/Brushes.cs | 222 --------- .../Processing/ColorStop.cs | 35 -- .../Processing/DrawingHelpers.cs | 22 - .../Processing/EllipticGradientBrush.cs | 165 ------- .../Extensions/DrawBezierExtensions.cs | 106 ---- .../Extensions/DrawLineExtensions.cs | 106 ---- .../DrawPathCollectionExtensions.cs | 110 ----- .../Extensions/DrawPathExtensions.cs | 103 ---- .../Extensions/DrawPolygonExtensions.cs | 106 ---- .../Extensions/DrawRectangleExtensions.cs | 103 ---- .../Extensions/DrawTextExtensions.cs | 179 ------- .../Extensions/FillPathBuilderExtensions.cs | 76 --- .../FillPathCollectionExtensions.cs | 76 --- .../Extensions/FillPathExtensions.cs | 64 --- .../Extensions/FillPolygonExtensions.cs | 70 --- .../Extensions/FillRectangleExtensions.cs | 66 --- .../Extensions/FillRegionExtensions.cs | 95 ---- .../Processing/GradientBrush.cs | 164 ------- .../Processing/GradientRepetitionMode.cs | 37 -- src/ImageSharp.Drawing/Processing/IBrush.cs | 40 -- src/ImageSharp.Drawing/Processing/IPen.cs | 28 -- .../Processing/ImageBrush.cs | 173 ------- .../Processing/LinearGradientBrush.cs | 160 ------- .../Processing/PathGradientBrush.cs | 309 ------------ .../Processing/PatternBrush.cs | 178 ------- src/ImageSharp.Drawing/Processing/Pen.cs | 76 --- src/ImageSharp.Drawing/Processing/Pens.cs | 97 ---- .../Processors/Drawing/FillProcessor.cs | 41 -- .../Drawing/FillProcessor{TPixel}.cs | 122 ----- .../Processors/Drawing/FillRegionProcessor.cs | 49 -- .../Drawing/FillRegionProcessor{TPixel}.cs | 197 -------- .../Processors/Text/DrawTextProcessor.cs | 79 --- .../Text/DrawTextProcessor{TPixel}.cs | 453 ------------------ .../Processing/RadialGradientBrush.cs | 104 ---- .../Processing/RecolorBrush.cs | 166 ------- .../Processing/SolidBrush.cs | 139 ------ .../Processing/TextGraphicsOptions.cs | 217 --------- src/ImageSharp.Drawing/Utils/NumberUtils.cs | 29 -- src/ImageSharp.Drawing/Utils/QuickSort.cs | 84 ---- .../Extensions/DrawImageExtensions.cs | 0 .../Processors/Drawing/DrawImageProcessor.cs | 0 .../DrawImageProcessor{TPixelBg,TPixelFg}.cs | 0 .../Drawing/DrawBeziers.cs | 63 --- .../Drawing/DrawLines.cs | 62 --- .../Drawing/DrawPolygon.cs | 60 --- .../ImageSharp.Benchmarks/Drawing/DrawText.cs | 96 ---- .../Drawing/DrawTextOutline.cs | 102 ---- .../Drawing/FillPolygon.cs | 84 ---- .../Drawing/FillRectangle.cs | 59 --- .../Drawing/FillWithPattern.cs | 53 -- .../ImageSharp.Benchmarks.csproj | 1 - .../ImageSharp.Sandbox46.csproj | 1 - .../Drawing/DrawBezierTests.cs | 47 -- .../Drawing/DrawComplexPolygonTests.cs | 69 --- .../Drawing/DrawImageTests.cs | 4 +- .../Drawing/DrawLinesTests.cs | 99 ---- .../ImageSharp.Tests/Drawing/DrawPathTests.cs | 78 --- .../Drawing/DrawPolygonTests.cs | 41 -- .../Drawing/FillComplexPolygonTests.cs | 61 --- .../Drawing/FillEllipticGradientBrushTest.cs | 147 ------ .../Drawing/FillImageBrushTests.cs | 50 -- .../Drawing/FillLinearGradientBrushTests.cs | 453 ------------------ .../Drawing/FillPathGradientBrushTests.cs | 157 ------ .../Drawing/FillPatternBrushTests.cs | 278 ----------- .../Drawing/FillPolygonTests.cs | 154 ------ .../Drawing/FillRadialGradientBrushTests.cs | 73 --- .../Drawing/FillRegionProcessorTests.cs | 156 ------ .../Drawing/FillSolidBrushTests.cs | 201 -------- .../Drawing/Paths/DrawPathCollection.cs | 119 ----- .../Drawing/Paths/FillPath.cs | 94 ---- .../Drawing/Paths/FillPathCollection.cs | 123 ----- .../Drawing/Paths/FillPolygon.cs | 95 ---- .../Drawing/Paths/FillRectangle.cs | 97 ---- .../Drawing/Paths/ShapePathTests.cs | 10 - .../Drawing/Paths/ShapeRegionTests.cs | 127 ----- .../Drawing/RecolorImageTests.cs | 52 -- .../Drawing/SolidBezierTests.cs | 64 --- .../Drawing/SolidFillBlendedShapesTests.cs | 178 ------- .../ImageSharp.Tests/Drawing/Text/DrawText.cs | 154 ------ .../Drawing/Text/DrawTextOnImageTests.cs | 265 ---------- .../Drawing/Text/TextGraphicsOptionsTests.cs | 211 -------- .../Drawing/Utils/QuickSortTests.cs | 51 -- .../ImageSharp.Tests/GraphicsOptionsTests.cs | 10 - .../Image/ImageTests.WrapMemory.cs | 22 +- .../ImageSharp.Tests/ImageSharp.Tests.csproj | 1 - tests/ImageSharp.Tests/Issues/Issue412.cs | 51 -- .../ImageProviders/SolidProvider.cs | 7 +- .../Tests/TestEnvironmentTests.cs | 46 +- 98 files changed, 45 insertions(+), 9368 deletions(-) delete mode 100644 src/ImageSharp.Drawing/Common/Extensions/GraphicsOptionsExtensions.cs delete mode 100644 src/ImageSharp.Drawing/ImageSharp.Drawing.csproj delete mode 100644 src/ImageSharp.Drawing/ImageSharp.Drawing.csproj.DotSettings delete mode 100644 src/ImageSharp.Drawing/Primitives/Region.cs delete mode 100644 src/ImageSharp.Drawing/Primitives/ShapePath.cs delete mode 100644 src/ImageSharp.Drawing/Primitives/ShapeRegion.cs delete mode 100644 src/ImageSharp.Drawing/Processing/BrushApplicator.cs delete mode 100644 src/ImageSharp.Drawing/Processing/Brushes.cs delete mode 100644 src/ImageSharp.Drawing/Processing/ColorStop.cs delete mode 100644 src/ImageSharp.Drawing/Processing/DrawingHelpers.cs delete mode 100644 src/ImageSharp.Drawing/Processing/EllipticGradientBrush.cs delete mode 100644 src/ImageSharp.Drawing/Processing/Extensions/DrawBezierExtensions.cs delete mode 100644 src/ImageSharp.Drawing/Processing/Extensions/DrawLineExtensions.cs delete mode 100644 src/ImageSharp.Drawing/Processing/Extensions/DrawPathCollectionExtensions.cs delete mode 100644 src/ImageSharp.Drawing/Processing/Extensions/DrawPathExtensions.cs delete mode 100644 src/ImageSharp.Drawing/Processing/Extensions/DrawPolygonExtensions.cs delete mode 100644 src/ImageSharp.Drawing/Processing/Extensions/DrawRectangleExtensions.cs delete mode 100644 src/ImageSharp.Drawing/Processing/Extensions/DrawTextExtensions.cs delete mode 100644 src/ImageSharp.Drawing/Processing/Extensions/FillPathBuilderExtensions.cs delete mode 100644 src/ImageSharp.Drawing/Processing/Extensions/FillPathCollectionExtensions.cs delete mode 100644 src/ImageSharp.Drawing/Processing/Extensions/FillPathExtensions.cs delete mode 100644 src/ImageSharp.Drawing/Processing/Extensions/FillPolygonExtensions.cs delete mode 100644 src/ImageSharp.Drawing/Processing/Extensions/FillRectangleExtensions.cs delete mode 100644 src/ImageSharp.Drawing/Processing/Extensions/FillRegionExtensions.cs delete mode 100644 src/ImageSharp.Drawing/Processing/GradientBrush.cs delete mode 100644 src/ImageSharp.Drawing/Processing/GradientRepetitionMode.cs delete mode 100644 src/ImageSharp.Drawing/Processing/IBrush.cs delete mode 100644 src/ImageSharp.Drawing/Processing/IPen.cs delete mode 100644 src/ImageSharp.Drawing/Processing/ImageBrush.cs delete mode 100644 src/ImageSharp.Drawing/Processing/LinearGradientBrush.cs delete mode 100644 src/ImageSharp.Drawing/Processing/PathGradientBrush.cs delete mode 100644 src/ImageSharp.Drawing/Processing/PatternBrush.cs delete mode 100644 src/ImageSharp.Drawing/Processing/Pen.cs delete mode 100644 src/ImageSharp.Drawing/Processing/Pens.cs delete mode 100644 src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs delete mode 100644 src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor{TPixel}.cs delete mode 100644 src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs delete mode 100644 src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor{TPixel}.cs delete mode 100644 src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs delete mode 100644 src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor{TPixel}.cs delete mode 100644 src/ImageSharp.Drawing/Processing/RadialGradientBrush.cs delete mode 100644 src/ImageSharp.Drawing/Processing/RecolorBrush.cs delete mode 100644 src/ImageSharp.Drawing/Processing/SolidBrush.cs delete mode 100644 src/ImageSharp.Drawing/Processing/TextGraphicsOptions.cs delete mode 100644 src/ImageSharp.Drawing/Utils/NumberUtils.cs delete mode 100644 src/ImageSharp.Drawing/Utils/QuickSort.cs rename src/{ImageSharp.Drawing => ImageSharp/Drawing}/Processing/Extensions/DrawImageExtensions.cs (100%) rename src/{ImageSharp.Drawing => ImageSharp/Drawing}/Processing/Processors/Drawing/DrawImageProcessor.cs (100%) rename src/{ImageSharp.Drawing => ImageSharp/Drawing}/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs (100%) delete mode 100644 tests/ImageSharp.Benchmarks/Drawing/DrawBeziers.cs delete mode 100644 tests/ImageSharp.Benchmarks/Drawing/DrawLines.cs delete mode 100644 tests/ImageSharp.Benchmarks/Drawing/DrawPolygon.cs delete mode 100644 tests/ImageSharp.Benchmarks/Drawing/DrawText.cs delete mode 100644 tests/ImageSharp.Benchmarks/Drawing/DrawTextOutline.cs delete mode 100644 tests/ImageSharp.Benchmarks/Drawing/FillPolygon.cs delete mode 100644 tests/ImageSharp.Benchmarks/Drawing/FillRectangle.cs delete mode 100644 tests/ImageSharp.Benchmarks/Drawing/FillWithPattern.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/DrawBezierTests.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/DrawComplexPolygonTests.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/DrawLinesTests.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/DrawPathTests.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/DrawPolygonTests.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/FillComplexPolygonTests.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/FillEllipticGradientBrushTest.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/FillImageBrushTests.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/FillPathGradientBrushTests.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/FillPatternBrushTests.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/FillPolygonTests.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/FillRadialGradientBrushTests.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/FillSolidBrushTests.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/Paths/DrawPathCollection.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/Paths/FillPath.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/Paths/FillPathCollection.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/Paths/FillPolygon.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/Paths/FillRectangle.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/Paths/ShapePathTests.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/Paths/ShapeRegionTests.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/RecolorImageTests.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/SolidBezierTests.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/SolidFillBlendedShapesTests.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/Text/DrawText.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/Text/TextGraphicsOptionsTests.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/Utils/QuickSortTests.cs delete mode 100644 tests/ImageSharp.Tests/Issues/Issue412.cs diff --git a/ImageSharp.sln b/ImageSharp.sln index d4a0419ee..227512cd1 100644 --- a/ImageSharp.sln +++ b/ImageSharp.sln @@ -64,8 +64,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{815C0625-CD3 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageSharp", "src\ImageSharp\ImageSharp.csproj", "{2AA31A1F-142C-43F4-8687-09ABCA4B3A26}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageSharp.Drawing", "src\ImageSharp.Drawing\ImageSharp.Drawing.csproj", "{2E33181E-6E28-4662-A801-E2E7DC206029}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{56801022-D71A-4FBE-BC5B-CBA08E2284EC}" ProjectSection(SolutionItems) = preProject tests\Directory.Build.props = tests\Directory.Build.props @@ -378,18 +376,6 @@ Global {2AA31A1F-142C-43F4-8687-09ABCA4B3A26}.Release|x64.Build.0 = Release|Any CPU {2AA31A1F-142C-43F4-8687-09ABCA4B3A26}.Release|x86.ActiveCfg = Release|Any CPU {2AA31A1F-142C-43F4-8687-09ABCA4B3A26}.Release|x86.Build.0 = Release|Any CPU - {2E33181E-6E28-4662-A801-E2E7DC206029}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2E33181E-6E28-4662-A801-E2E7DC206029}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2E33181E-6E28-4662-A801-E2E7DC206029}.Debug|x64.ActiveCfg = Debug|Any CPU - {2E33181E-6E28-4662-A801-E2E7DC206029}.Debug|x64.Build.0 = Debug|Any CPU - {2E33181E-6E28-4662-A801-E2E7DC206029}.Debug|x86.ActiveCfg = Debug|Any CPU - {2E33181E-6E28-4662-A801-E2E7DC206029}.Debug|x86.Build.0 = Debug|Any CPU - {2E33181E-6E28-4662-A801-E2E7DC206029}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2E33181E-6E28-4662-A801-E2E7DC206029}.Release|Any CPU.Build.0 = Release|Any CPU - {2E33181E-6E28-4662-A801-E2E7DC206029}.Release|x64.ActiveCfg = Release|Any CPU - {2E33181E-6E28-4662-A801-E2E7DC206029}.Release|x64.Build.0 = Release|Any CPU - {2E33181E-6E28-4662-A801-E2E7DC206029}.Release|x86.ActiveCfg = Release|Any CPU - {2E33181E-6E28-4662-A801-E2E7DC206029}.Release|x86.Build.0 = Release|Any CPU {EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6}.Debug|Any CPU.Build.0 = Debug|Any CPU {EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -434,7 +420,6 @@ Global {FBE8C1AD-5AEC-4514-9B64-091D8E145865} = {1799C43E-5C54-4A8F-8D64-B1475241DB0D} {2B02E303-7CC6-4E15-97EE-DBE86B287553} = {E919DF0B-2607-4462-8FC0-5C98FE50F8C9} {2AA31A1F-142C-43F4-8687-09ABCA4B3A26} = {815C0625-CD3D-440F-9F80-2D83856AB7AE} - {2E33181E-6E28-4662-A801-E2E7DC206029} = {815C0625-CD3D-440F-9F80-2D83856AB7AE} {D4C5EC58-F8E6-4636-B9EE-C99D2578E5C6} = {56801022-D71A-4FBE-BC5B-CBA08E2284EC} {FA55F5DE-11A6-487D-ABA4-BC93A02717DD} = {56801022-D71A-4FBE-BC5B-CBA08E2284EC} {9DA226A1-8656-49A8-A58A-A8B5C081AD66} = {FA55F5DE-11A6-487D-ABA4-BC93A02717DD} diff --git a/appveyor.yml b/appveyor.yml index 2cc5182d3..2588b8065 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -55,7 +55,6 @@ test_script: after_test: - cmd: appveyor PushArtifact "artifacts\SixLabors.ImageSharp.%APPVEYOR_BUILD_VERSION%.nupkg" - - cmd: appveyor PushArtifact "artifacts\SixLabors.ImageSharp.Drawing.%APPVEYOR_BUILD_VERSION%.nupkg" deploy: # MyGet Deployment for builds & releases @@ -66,4 +65,4 @@ deploy: secure: V/lEHP0UeMWIpWd0fiNlY2IgbCnJKQlGdRksECdJbOBdaE20Fl0RNL7WyqHe02o4 artifact: /.*\.nupkg/ on: - branch: master \ No newline at end of file + branch: master diff --git a/build.ps1 b/build.ps1 index 215b55117..4584ebc60 100644 --- a/build.ps1 +++ b/build.ps1 @@ -117,6 +117,3 @@ if ($LASTEXITCODE ){ Exit $LASTEXITCODE } Write-Host "Packaging projects" dotnet pack ./src/ImageSharp/ -c Release --output ../../artifacts --no-build /p:packageversion=$version if ($LASTEXITCODE ){ Exit $LASTEXITCODE } - -dotnet pack ./src/ImageSharp.Drawing/ -c Release --output ../../artifacts --no-build /p:packageversion=$version -if ($LASTEXITCODE ){ Exit $LASTEXITCODE } diff --git a/src/ImageSharp.Drawing/Common/Extensions/GraphicsOptionsExtensions.cs b/src/ImageSharp.Drawing/Common/Extensions/GraphicsOptionsExtensions.cs deleted file mode 100644 index c32d0a46e..000000000 --- a/src/ImageSharp.Drawing/Common/Extensions/GraphicsOptionsExtensions.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Numerics; -using SixLabors.ImageSharp.PixelFormats; - -namespace SixLabors.ImageSharp -{ - /// - /// Extensions methods fpor the class. - /// - internal static class GraphicsOptionsExtensions - { - /// - /// Evaluates if a given SOURCE color can completely replace a BACKDROP color given the current blending and composition settings. - /// - /// The graphics options. - /// The source color. - /// true if the color can be considered opaque - /// - /// Blending and composition is an expensive operation, in some cases, like - /// filling with a solid color, the blending can be avoided by a plain color replacement. - /// This method can be useful for such processors to select the fast path. - /// - public static bool IsOpaqueColorWithoutBlending(this GraphicsOptions options, Color color) - { - if (options.ColorBlendingMode != PixelColorBlendingMode.Normal) - { - return false; - } - - if (options.AlphaCompositionMode != PixelAlphaCompositionMode.SrcOver - && options.AlphaCompositionMode != PixelAlphaCompositionMode.Src) - { - return false; - } - - const float Opaque = 1F; - - if (options.BlendPercentage != Opaque) - { - return false; - } - - if (((Vector4)color).W != Opaque) - { - return false; - } - - return true; - } - } -} diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj deleted file mode 100644 index c4e3224bb..000000000 --- a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj +++ /dev/null @@ -1,24 +0,0 @@ - - - - - SixLabors.ImageSharp.Drawing - SixLabors.ImageSharp.Drawing - An extension to ImageSharp that allows the drawing of images, paths, and text. - SixLabors.ImageSharp.Drawing - Image Draw Shape Path Font - SixLabors.ImageSharp - - netcoreapp2.1;netstandard2.0;netstandard1.3 - - - - - - - - - - - - diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj.DotSettings b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj.DotSettings deleted file mode 100644 index a728b5497..000000000 --- a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj.DotSettings +++ /dev/null @@ -1,2 +0,0 @@ - - True \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Primitives/Region.cs b/src/ImageSharp.Drawing/Primitives/Region.cs deleted file mode 100644 index 27f039f12..000000000 --- a/src/ImageSharp.Drawing/Primitives/Region.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using SixLabors.Primitives; - -namespace SixLabors.ImageSharp.Primitives -{ - /// - /// Represents a region of an image. - /// - public abstract class Region - { - /// - /// Gets the maximum number of intersections to could be returned. - /// - public abstract int MaxIntersections { get; } - - /// - /// Gets the bounding box that entirely surrounds this region. - /// - /// - /// This should always contains all possible points returned from . - /// - public abstract Rectangle Bounds { get; } - - /// - /// Scans the X axis for intersections at the Y axis position. - /// - /// The position along the y axis to find intersections. - /// The buffer. - /// A instance in the context of the caller. - /// The number of intersections found. - public abstract int Scan(float y, Span buffer, Configuration configuration); - } -} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Primitives/ShapePath.cs b/src/ImageSharp.Drawing/Primitives/ShapePath.cs deleted file mode 100644 index a4fef66a6..000000000 --- a/src/ImageSharp.Drawing/Primitives/ShapePath.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.Processing; -using SixLabors.Shapes; - -namespace SixLabors.ImageSharp.Primitives -{ - /// - /// A mapping between a and a region. - /// - internal class ShapePath : ShapeRegion - { - /// - /// Initializes a new instance of the class. - /// - /// The shape. - /// The pen to apply to the shape. - public ShapePath(IPath shape, IPen pen) - : base(shape.GenerateOutline(pen.StrokeWidth, pen.StrokePattern)) - { - } - } -} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Primitives/ShapeRegion.cs b/src/ImageSharp.Drawing/Primitives/ShapeRegion.cs deleted file mode 100644 index c008f4419..000000000 --- a/src/ImageSharp.Drawing/Primitives/ShapeRegion.cs +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Buffers; - -using SixLabors.ImageSharp.Memory; -using SixLabors.Primitives; -using SixLabors.Shapes; - -namespace SixLabors.ImageSharp.Primitives -{ - /// - /// A mapping between a and a region. - /// - internal class ShapeRegion : Region - { - /// - /// Initializes a new instance of the class. - /// - /// The shape. - public ShapeRegion(IPath shape) - { - this.Shape = shape.AsClosedPath(); - int left = (int)MathF.Floor(shape.Bounds.Left); - int top = (int)MathF.Floor(shape.Bounds.Top); - - int right = (int)MathF.Ceiling(shape.Bounds.Right); - int bottom = (int)MathF.Ceiling(shape.Bounds.Bottom); - this.Bounds = Rectangle.FromLTRB(left, top, right, bottom); - } - - /// - /// Gets the fillable shape - /// - public IPath Shape { get; } - - /// - public override int MaxIntersections => this.Shape.MaxIntersections; - - /// - public override Rectangle Bounds { get; } - - /// - public override int Scan(float y, Span buffer, Configuration configuration) - { - var start = new PointF(this.Bounds.Left - 1, y); - var end = new PointF(this.Bounds.Right + 1, y); - - using (IMemoryOwner tempBuffer = configuration.MemoryAllocator.Allocate(buffer.Length)) - { - Span innerBuffer = tempBuffer.Memory.Span; - int count = this.Shape.FindIntersections(start, end, innerBuffer); - - for (int i = 0; i < count; i++) - { - buffer[i] = innerBuffer[i].X; - } - - return count; - } - } - } -} diff --git a/src/ImageSharp.Drawing/Processing/BrushApplicator.cs b/src/ImageSharp.Drawing/Processing/BrushApplicator.cs deleted file mode 100644 index 058c6d0eb..000000000 --- a/src/ImageSharp.Drawing/Processing/BrushApplicator.cs +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Buffers; -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Memory; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// A primitive that converts a point into a color for discovering the fill color based on an implementation. - /// - /// The pixel format. - /// - public abstract class BrushApplicator : IDisposable - where TPixel : struct, IPixel - { - /// - /// Initializes a new instance of the class. - /// - /// The configuration instance to use when performing operations. - /// The graphics options. - /// The target. - internal BrushApplicator(Configuration configuration, GraphicsOptions options, ImageFrame target) - { - this.Configuration = configuration; - this.Target = target; - this.Options = options; - this.Blender = PixelOperations.Instance.GetPixelBlender(options); - } - - /// - /// Gets the configuration instance to use when performing operations. - /// - protected Configuration Configuration { get; } - - /// - /// Gets the pixel blender. - /// - internal PixelBlender Blender { get; } - - /// - /// Gets the target image. - /// - protected ImageFrame Target { get; } - - /// - /// Gets thegraphics options - /// - protected GraphicsOptions Options { get; } - - /// - /// Gets the overlay pixel at the specified position. - /// - /// The x-coordinate. - /// The y-coordinate. - /// The at the specified position. - internal abstract TPixel this[int x, int y] { get; } - - /// - public void Dispose() - { - this.Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// Disposes the object and frees resources for the Garbage Collector. - /// - /// Whether to dispose managed and unmanaged objects. - protected virtual void Dispose(bool disposing) - { - } - - /// - /// Applies the opacity weighting for each pixel in a scanline to the target based on the pattern contained in the brush. - /// - /// A collection of opacity values between 0 and 1 to be merged with the brushed color value before being applied to the target. - /// The x-position in the target pixel space that the start of the scanline data corresponds to. - /// The y-position in the target pixel space that whole scanline corresponds to. - /// scanlineBuffer will be > scanlineWidth but provide and offset in case we want to share a larger buffer across runs. - internal virtual void Apply(Span scanline, int x, int y) - { - MemoryAllocator memoryAllocator = this.Target.MemoryAllocator; - - using (IMemoryOwner amountBuffer = memoryAllocator.Allocate(scanline.Length)) - using (IMemoryOwner overlay = memoryAllocator.Allocate(scanline.Length)) - { - Span amountSpan = amountBuffer.Memory.Span; - Span overlaySpan = overlay.Memory.Span; - float blendPercentage = this.Options.BlendPercentage; - - if (blendPercentage < 1) - { - for (int i = 0; i < scanline.Length; i++) - { - amountSpan[i] = scanline[i] * blendPercentage; - overlaySpan[i] = this[x + i, y]; - } - } - else - { - for (int i = 0; i < scanline.Length; i++) - { - amountSpan[i] = scanline[i]; - overlaySpan[i] = this[x + i, y]; - } - } - - Span destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length); - this.Blender.Blend(this.Configuration, destinationRow, destinationRow, overlaySpan, amountSpan); - } - } - } -} diff --git a/src/ImageSharp.Drawing/Processing/Brushes.cs b/src/ImageSharp.Drawing/Processing/Brushes.cs deleted file mode 100644 index bd10e90c6..000000000 --- a/src/ImageSharp.Drawing/Processing/Brushes.cs +++ /dev/null @@ -1,222 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// A collection of methods for creating generic brushes. - /// - /// A New - public static class Brushes - { - /// - /// Percent10 Hatch Pattern - /// - /// ---> x axis - /// ^ - /// | y - axis - /// | - /// see PatternBrush for details about how to make new patterns work - private static readonly bool[,] Percent10Pattern = - { - { true, false, false, false }, - { false, false, false, false }, - { false, false, true, false }, - { false, false, false, false } - }; - - /// - /// Percent20 pattern. - /// - private static readonly bool[,] Percent20Pattern = - { - { true, false, false, false }, - { false, false, true, false }, - { true, false, false, false }, - { false, false, true, false } - }; - - /// - /// Horizontal Hatch Pattern - /// - private static readonly bool[,] HorizontalPattern = - { - { false }, - { true }, - { false }, - { false } - }; - - /// - /// Min Pattern - /// - private static readonly bool[,] MinPattern = - { - { false }, - { false }, - { false }, - { true } - }; - - /// - /// Vertical Pattern - /// - private static readonly bool[,] VerticalPattern = - { - { false, true, false, false }, - }; - - /// - /// Forward Diagonal Pattern - /// - private static readonly bool[,] ForwardDiagonalPattern = - { - { false, false, false, true }, - { false, false, true, false }, - { false, true, false, false }, - { true, false, false, false } - }; - - /// - /// Backward Diagonal Pattern - /// - private static readonly bool[,] BackwardDiagonalPattern = - { - { true, false, false, false }, - { false, true, false, false }, - { false, false, true, false }, - { false, false, false, true } - }; - - /// - /// Create as brush that will paint a solid color - /// - /// The color. - /// A New - public static SolidBrush Solid(Color color) => new SolidBrush(color); - - /// - /// Create as brush that will paint a Percent10 Hatch Pattern with the specified colors - /// - /// Color of the foreground. - /// A New - public static PatternBrush Percent10(Color foreColor) => - new PatternBrush(foreColor, Color.Transparent, Percent10Pattern); - - /// - /// Create as brush that will paint a Percent10 Hatch Pattern with the specified colors - /// - /// Color of the foreground. - /// Color of the background. - /// A New - public static PatternBrush Percent10(Color foreColor, Color backColor) => - new PatternBrush(foreColor, backColor, Percent10Pattern); - - /// - /// Create as brush that will paint a Percent20 Hatch Pattern with the specified foreground color and a - /// transparent background. - /// - /// Color of the foreground. - /// A New - public static PatternBrush Percent20(Color foreColor) => - new PatternBrush(foreColor, Color.Transparent, Percent20Pattern); - - /// - /// Create as brush that will paint a Percent20 Hatch Pattern with the specified colors - /// - /// Color of the foreground. - /// Color of the background. - /// A New - public static PatternBrush Percent20(Color foreColor, Color backColor) => - new PatternBrush(foreColor, backColor, Percent20Pattern); - - /// - /// Create as brush that will paint a Horizontal Hatch Pattern with the specified foreground color and a - /// transparent background. - /// - /// Color of the foreground. - /// A New - public static PatternBrush Horizontal(Color foreColor) => - new PatternBrush(foreColor, Color.Transparent, HorizontalPattern); - - /// - /// Create as brush that will paint a Horizontal Hatch Pattern with the specified colors - /// - /// Color of the foreground. - /// Color of the background. - /// A New - public static PatternBrush Horizontal(Color foreColor, Color backColor) => - new PatternBrush(foreColor, backColor, HorizontalPattern); - - /// - /// Create as brush that will paint a Min Hatch Pattern with the specified foreground color and a - /// transparent background. - /// - /// Color of the foreground. - /// A New - public static PatternBrush Min(Color foreColor) => new PatternBrush(foreColor, Color.Transparent, MinPattern); - - /// - /// Create as brush that will paint a Min Hatch Pattern with the specified colors - /// - /// Color of the foreground. - /// Color of the background. - /// A New - public static PatternBrush Min(Color foreColor, Color backColor) => - new PatternBrush(foreColor, backColor, MinPattern); - - /// - /// Create as brush that will paint a Vertical Hatch Pattern with the specified foreground color and a - /// transparent background. - /// - /// Color of the foreground. - /// A New - public static PatternBrush Vertical(Color foreColor) => - new PatternBrush(foreColor, Color.Transparent, VerticalPattern); - - /// - /// Create as brush that will paint a Vertical Hatch Pattern with the specified colors - /// - /// Color of the foreground. - /// Color of the background. - /// A New - public static PatternBrush Vertical(Color foreColor, Color backColor) => - new PatternBrush(foreColor, backColor, VerticalPattern); - - /// - /// Create as brush that will paint a Forward Diagonal Hatch Pattern with the specified foreground color and a - /// transparent background. - /// - /// Color of the foreground. - /// A New - public static PatternBrush ForwardDiagonal(Color foreColor) => - new PatternBrush(foreColor, Color.Transparent, ForwardDiagonalPattern); - - /// - /// Create as brush that will paint a Forward Diagonal Hatch Pattern with the specified colors - /// - /// Color of the foreground. - /// Color of the background. - /// A New - public static PatternBrush ForwardDiagonal(Color foreColor, Color backColor) => - new PatternBrush(foreColor, backColor, ForwardDiagonalPattern); - - /// - /// Create as brush that will paint a Backward Diagonal Hatch Pattern with the specified foreground color and a - /// transparent background. - /// - /// Color of the foreground. - /// A New - public static PatternBrush BackwardDiagonal(Color foreColor) => - new PatternBrush(foreColor, Color.Transparent, BackwardDiagonalPattern); - - /// - /// Create as brush that will paint a Backward Diagonal Hatch Pattern with the specified colors - /// - /// Color of the foreground. - /// Color of the background. - /// A New - public static PatternBrush BackwardDiagonal(Color foreColor, Color backColor) => - new PatternBrush(foreColor, backColor, BackwardDiagonalPattern); - } -} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/ColorStop.cs b/src/ImageSharp.Drawing/Processing/ColorStop.cs deleted file mode 100644 index 21c82b63f..000000000 --- a/src/ImageSharp.Drawing/Processing/ColorStop.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Diagnostics; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// A struct that defines a single color stop. - /// - [DebuggerDisplay("ColorStop({Ratio} -> {Color}")] - public readonly struct ColorStop - { - /// - /// Initializes a new instance of the struct. - /// - /// Where should it be? 0 is at the start, 1 at the end of the Gradient. - /// What color should be used at that point? - public ColorStop(float ratio, in Color color) - { - this.Ratio = ratio; - this.Color = color; - } - - /// - /// Gets the point along the defined gradient axis. - /// - public float Ratio { get; } - - /// - /// Gets the color to be used. - /// - public Color Color { get; } - } -} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/DrawingHelpers.cs b/src/ImageSharp.Drawing/Processing/DrawingHelpers.cs deleted file mode 100644 index 25a8204f2..000000000 --- a/src/ImageSharp.Drawing/Processing/DrawingHelpers.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Primitives; - -namespace SixLabors.ImageSharp.Processing -{ - internal static class DrawingHelpers - { - /// - /// Convert a to a of the given pixel type. - /// - public static DenseMatrix ToPixelMatrix(this DenseMatrix colorMatrix, Configuration configuration) - where TPixel : struct, IPixel - { - var result = new DenseMatrix(colorMatrix.Columns, colorMatrix.Rows); - Color.ToPixel(configuration, colorMatrix.Span, result.Span); - return result; - } - } -} diff --git a/src/ImageSharp.Drawing/Processing/EllipticGradientBrush.cs b/src/ImageSharp.Drawing/Processing/EllipticGradientBrush.cs deleted file mode 100644 index fbab3605d..000000000 --- a/src/ImageSharp.Drawing/Processing/EllipticGradientBrush.cs +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Primitives; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// Gradient Brush with elliptic shape. - /// The ellipse is defined by a center point, - /// a point on the longest extension of the ellipse and - /// the ratio between longest and shortest extension. - /// - public sealed class EllipticGradientBrush : GradientBrush - { - private readonly PointF center; - - private readonly PointF referenceAxisEnd; - - private readonly float axisRatio; - - /// - /// The center of the elliptical gradient and 0 for the color stops. - /// The end point of the reference axis of the ellipse. - /// - /// The ratio of the axis widths. - /// The second axis' is perpendicular to the reference axis and - /// it's length is the reference axis' length multiplied by this factor. - /// - /// Defines how the colors of the gradients are repeated. - /// the color stops as defined in base class. - public EllipticGradientBrush( - PointF center, - PointF referenceAxisEnd, - float axisRatio, - GradientRepetitionMode repetitionMode, - params ColorStop[] colorStops) - : base(repetitionMode, colorStops) - { - this.center = center; - this.referenceAxisEnd = referenceAxisEnd; - this.axisRatio = axisRatio; - } - - /// - public override BrushApplicator CreateApplicator( - Configuration configuration, - GraphicsOptions options, - ImageFrame source, - RectangleF region) => - new RadialGradientBrushApplicator( - configuration, - options, - source, - this.center, - this.referenceAxisEnd, - this.axisRatio, - this.ColorStops, - this.RepetitionMode); - - /// - private sealed class RadialGradientBrushApplicator : GradientBrushApplicator - where TPixel : struct, IPixel - { - private readonly PointF center; - - private readonly PointF referenceAxisEnd; - - private readonly float axisRatio; - - private readonly double rotation; - - private readonly float referenceRadius; - - private readonly float secondRadius; - - private readonly float cosRotation; - - private readonly float sinRotation; - - private readonly float secondRadiusSquared; - - private readonly float referenceRadiusSquared; - - /// - /// Initializes a new instance of the class. - /// - /// The configuration instance to use when performing operations. - /// The graphics options. - /// The target image. - /// Center of the ellipse. - /// Point on one angular points of the ellipse. - /// - /// Ratio of the axis length's. Used to determine the length of the second axis, - /// the first is defined by and . - /// Definition of colors. - /// Defines how the gradient colors are repeated. - public RadialGradientBrushApplicator( - Configuration configuration, - GraphicsOptions options, - ImageFrame target, - PointF center, - PointF referenceAxisEnd, - float axisRatio, - ColorStop[] colorStops, - GradientRepetitionMode repetitionMode) - : base(configuration, options, target, colorStops, repetitionMode) - { - this.center = center; - this.referenceAxisEnd = referenceAxisEnd; - this.axisRatio = axisRatio; - this.rotation = this.AngleBetween( - this.center, - new PointF(this.center.X + 1, this.center.Y), - this.referenceAxisEnd); - this.referenceRadius = this.DistanceBetween(this.center, this.referenceAxisEnd); - this.secondRadius = this.referenceRadius * this.axisRatio; - - this.referenceRadiusSquared = this.referenceRadius * this.referenceRadius; - this.secondRadiusSquared = this.secondRadius * this.secondRadius; - - this.sinRotation = (float)Math.Sin(this.rotation); - this.cosRotation = (float)Math.Cos(this.rotation); - } - - /// - protected override float PositionOnGradient(float xt, float yt) - { - float x0 = xt - this.center.X; - float y0 = yt - this.center.Y; - - float x = (x0 * this.cosRotation) - (y0 * this.sinRotation); - float y = (x0 * this.sinRotation) + (y0 * this.cosRotation); - - float xSquared = x * x; - float ySquared = y * y; - - return (xSquared / this.referenceRadiusSquared) + (ySquared / this.secondRadiusSquared); - } - - private float AngleBetween(PointF junction, PointF a, PointF b) - { - PointF vA = a - junction; - PointF vB = b - junction; - return MathF.Atan2(vB.Y, vB.X) - MathF.Atan2(vA.Y, vA.X); - } - - private float DistanceBetween( - PointF p1, - PointF p2) - { - // TODO: Can we not just use Vector2 distance here? - float dX = p1.X - p2.X; - float dXsquared = dX * dX; - - float dY = p1.Y - p2.Y; - float dYsquared = dY * dY; - return MathF.Sqrt(dXsquared + dYsquared); - } - } - } -} diff --git a/src/ImageSharp.Drawing/Processing/Extensions/DrawBezierExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/DrawBezierExtensions.cs deleted file mode 100644 index 7660e7225..000000000 --- a/src/ImageSharp.Drawing/Processing/Extensions/DrawBezierExtensions.cs +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.Primitives; -using SixLabors.Shapes; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// Adds extensions that allow the drawing of Bezier paths to the type. - /// - public static class DrawBezierExtensions - { - /// - /// Draws the provided points as an open Bezier path at the provided thickness with the supplied brush - /// - /// The image this method extends. - /// The options. - /// The brush. - /// The thickness. - /// The points. - /// The . - public static IImageProcessingContext DrawBeziers( - this IImageProcessingContext source, - GraphicsOptions options, - IBrush brush, - float thickness, - params PointF[] points) => - source.Draw(options, new Pen(brush, thickness), new Path(new CubicBezierLineSegment(points))); - - /// - /// Draws the provided points as an open Bezier path at the provided thickness with the supplied brush - /// - /// The image this method extends. - /// The brush. - /// The thickness. - /// The points. - /// The . - public static IImageProcessingContext DrawBeziers( - this IImageProcessingContext source, - IBrush brush, - float thickness, - params PointF[] points) => - source.Draw(new Pen(brush, thickness), new Path(new CubicBezierLineSegment(points))); - - /// - /// Draws the provided points as an open Bezier path at the provided thickness with the supplied brush - /// - /// The image this method extends. - /// The color. - /// The thickness. - /// The points. - /// The . - public static IImageProcessingContext DrawBeziers( - this IImageProcessingContext source, - Color color, - float thickness, - params PointF[] points) => - source.DrawBeziers(new SolidBrush(color), thickness, points); - - /// - /// Draws the provided points as an open Bezier path at the provided thickness with the supplied brush - /// - /// The image this method extends. - /// The options. - /// The color. - /// The thickness. - /// The points. - /// The . - public static IImageProcessingContext DrawBeziers( - this IImageProcessingContext source, - GraphicsOptions options, - Color color, - float thickness, - params PointF[] points) => - source.DrawBeziers(options, new SolidBrush(color), thickness, points); - - /// - /// Draws the provided points as an open Bezier path with the supplied pen - /// - /// The image this method extends. - /// The options. - /// The pen. - /// The points. - /// The . - public static IImageProcessingContext DrawBeziers( - this IImageProcessingContext source, - GraphicsOptions options, - IPen pen, - params PointF[] points) => - source.Draw(options, pen, new Path(new CubicBezierLineSegment(points))); - - /// - /// Draws the provided points as an open Bezier path with the supplied pen - /// - /// The image this method extends. - /// The pen. - /// The points. - /// The . - public static IImageProcessingContext DrawBeziers( - this IImageProcessingContext source, - IPen pen, - params PointF[] points) => - source.Draw(pen, new Path(new CubicBezierLineSegment(points))); - } -} diff --git a/src/ImageSharp.Drawing/Processing/Extensions/DrawLineExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/DrawLineExtensions.cs deleted file mode 100644 index 98e8fdc59..000000000 --- a/src/ImageSharp.Drawing/Processing/Extensions/DrawLineExtensions.cs +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.Primitives; -using SixLabors.Shapes; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// Adds extensions that allow the drawing of lines to the type. - /// - public static class DrawLineExtensions - { - /// - /// Draws the provided Points as an open Linear path at the provided thickness with the supplied brush - /// - /// The image this method extends. - /// The options. - /// The brush. - /// The thickness. - /// The points. - /// The . - public static IImageProcessingContext DrawLines( - this IImageProcessingContext source, - GraphicsOptions options, - IBrush brush, - float thickness, - params PointF[] points) => - source.Draw(options, new Pen(brush, thickness), new Path(new LinearLineSegment(points))); - - /// - /// Draws the provided Points as an open Linear path at the provided thickness with the supplied brush - /// - /// The image this method extends. - /// The brush. - /// The thickness. - /// The points. - /// The . - public static IImageProcessingContext DrawLines( - this IImageProcessingContext source, - IBrush brush, - float thickness, - params PointF[] points) => - source.Draw(new Pen(brush, thickness), new Path(new LinearLineSegment(points))); - - /// - /// Draws the provided Points as an open Linear path at the provided thickness with the supplied brush - /// - /// The image this method extends. - /// The color. - /// The thickness. - /// The points. - /// The . - public static IImageProcessingContext DrawLines( - this IImageProcessingContext source, - Color color, - float thickness, - params PointF[] points) => - source.DrawLines(new SolidBrush(color), thickness, points); - - /// - /// Draws the provided Points as an open Linear path at the provided thickness with the supplied brush - /// - /// The image this method extends. - /// The options. - /// The color. - /// The thickness. - /// The points. - /// The .> - public static IImageProcessingContext DrawLines( - this IImageProcessingContext source, - GraphicsOptions options, - Color color, - float thickness, - params PointF[] points) => - source.DrawLines(options, new SolidBrush(color), thickness, points); - - /// - /// Draws the provided Points as an open Linear path with the supplied pen - /// - /// The image this method extends. - /// The options. - /// The pen. - /// The points. - /// The . - public static IImageProcessingContext DrawLines( - this IImageProcessingContext source, - GraphicsOptions options, - IPen pen, - params PointF[] points) => - source.Draw(options, pen, new Path(new LinearLineSegment(points))); - - /// - /// Draws the provided Points as an open Linear path with the supplied pen - /// - /// The image this method extends. - /// The pen. - /// The points. - /// The . - public static IImageProcessingContext DrawLines( - this IImageProcessingContext source, - IPen pen, - params PointF[] points) => - source.Draw(pen, new Path(new LinearLineSegment(points))); - } -} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Extensions/DrawPathCollectionExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/DrawPathCollectionExtensions.cs deleted file mode 100644 index 90b8c68ac..000000000 --- a/src/ImageSharp.Drawing/Processing/Extensions/DrawPathCollectionExtensions.cs +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.Shapes; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// Adds extensions that allow the drawing of collections of polygon outlines to the type. - /// - public static class DrawPathCollectionExtensions - { - /// - /// Draws the outline of the polygon with the provided pen. - /// - /// The image this method extends. - /// The options. - /// The pen. - /// The paths. - /// The . - public static IImageProcessingContext Draw( - this IImageProcessingContext source, - GraphicsOptions options, - IPen pen, - IPathCollection paths) - { - foreach (IPath path in paths) - { - source.Draw(options, pen, path); - } - - return source; - } - - /// - /// Draws the outline of the polygon with the provided pen. - /// - /// The image this method extends. - /// The pen. - /// The paths. - /// The . - public static IImageProcessingContext - Draw(this IImageProcessingContext source, IPen pen, IPathCollection paths) => - source.Draw(new GraphicsOptions(), pen, paths); - - /// - /// Draws the outline of the polygon with the provided brush at the provided thickness. - /// - /// The image this method extends. - /// The options. - /// The brush. - /// The thickness. - /// The shapes. - /// The . - public static IImageProcessingContext Draw( - this IImageProcessingContext source, - GraphicsOptions options, - IBrush brush, - float thickness, - IPathCollection paths) => - source.Draw(options, new Pen(brush, thickness), paths); - - /// - /// Draws the outline of the polygon with the provided brush at the provided thickness. - /// - /// The image this method extends. - /// The brush. - /// The thickness. - /// The paths. - /// The . - public static IImageProcessingContext Draw( - this IImageProcessingContext source, - IBrush brush, - float thickness, - IPathCollection paths) => - source.Draw(new Pen(brush, thickness), paths); - - /// - /// Draws the outline of the polygon with the provided brush at the provided thickness. - /// - /// The image this method extends. - /// The options. - /// The color. - /// The thickness. - /// The paths. - /// The . - public static IImageProcessingContext Draw( - this IImageProcessingContext source, - GraphicsOptions options, - Color color, - float thickness, - IPathCollection paths) => - source.Draw(options, new SolidBrush(color), thickness, paths); - - /// - /// Draws the outline of the polygon with the provided brush at the provided thickness. - /// - /// The image this method extends. - /// The color. - /// The thickness. - /// The paths. - /// The . - public static IImageProcessingContext Draw( - this IImageProcessingContext source, - Color color, - float thickness, - IPathCollection paths) => - source.Draw(new SolidBrush(color), thickness, paths); - } -} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Extensions/DrawPathExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/DrawPathExtensions.cs deleted file mode 100644 index 822375ca9..000000000 --- a/src/ImageSharp.Drawing/Processing/Extensions/DrawPathExtensions.cs +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.Primitives; -using SixLabors.Shapes; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// Adds extensions that allow the drawing of polygon outlines to the type. - /// - public static class DrawPathExtensions - { - /// - /// Draws the outline of the polygon with the provided pen. - /// - /// The image this method extends. - /// The options. - /// The pen. - /// The path. - /// The . - public static IImageProcessingContext Draw( - this IImageProcessingContext source, - GraphicsOptions options, - IPen pen, - IPath path) => - source.Fill(options, pen.StrokeFill, new ShapePath(path, pen)); - - /// - /// Draws the outline of the polygon with the provided pen. - /// - /// The image this method extends. - /// The pen. - /// The path. - /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, IPen pen, IPath path) => - source.Draw(new GraphicsOptions(), pen, path); - - /// - /// Draws the outline of the polygon with the provided brush at the provided thickness. - /// - /// The image this method extends. - /// The options. - /// The brush. - /// The thickness. - /// The shape. - /// The . - public static IImageProcessingContext Draw( - this IImageProcessingContext source, - GraphicsOptions options, - IBrush brush, - float thickness, - IPath path) => - source.Draw(options, new Pen(brush, thickness), path); - - /// - /// Draws the outline of the polygon with the provided brush at the provided thickness. - /// - /// The image this method extends. - /// The brush. - /// The thickness. - /// The path. - /// The . - public static IImageProcessingContext Draw( - this IImageProcessingContext source, - IBrush brush, - float thickness, - IPath path) => - source.Draw(new Pen(brush, thickness), path); - - /// - /// Draws the outline of the polygon with the provided brush at the provided thickness. - /// - /// The image this method extends. - /// The options. - /// The color. - /// The thickness. - /// The path. - /// The . - public static IImageProcessingContext Draw( - this IImageProcessingContext source, - GraphicsOptions options, - Color color, - float thickness, - IPath path) => - source.Draw(options, new SolidBrush(color), thickness, path); - - /// - /// Draws the outline of the polygon with the provided brush at the provided thickness. - /// - /// The image this method extends. - /// The color. - /// The thickness. - /// The path. - /// The . - public static IImageProcessingContext Draw( - this IImageProcessingContext source, - Color color, - float thickness, - IPath path) => - source.Draw(new SolidBrush(color), thickness, path); - } -} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Extensions/DrawPolygonExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/DrawPolygonExtensions.cs deleted file mode 100644 index d51e58645..000000000 --- a/src/ImageSharp.Drawing/Processing/Extensions/DrawPolygonExtensions.cs +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.Primitives; -using SixLabors.Shapes; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// Adds extensions that allow the drawing of closed linear polygons to the type. - /// - public static class DrawPolygonExtensions - { - /// - /// Draws the provided Points as a closed Linear Polygon with the provided brush at the provided thickness. - /// - /// The image this method extends. - /// The options. - /// The brush. - /// The thickness. - /// The points. - /// The . - public static IImageProcessingContext DrawPolygon( - this IImageProcessingContext source, - GraphicsOptions options, - IBrush brush, - float thickness, - params PointF[] points) => - source.Draw(options, new Pen(brush, thickness), new Polygon(new LinearLineSegment(points))); - - /// - /// Draws the provided Points as a closed Linear Polygon with the provided brush at the provided thickness. - /// - /// The image this method extends. - /// The brush. - /// The thickness. - /// The points. - /// The . - public static IImageProcessingContext DrawPolygon( - this IImageProcessingContext source, - IBrush brush, - float thickness, - params PointF[] points) => - source.Draw(new Pen(brush, thickness), new Polygon(new LinearLineSegment(points))); - - /// - /// Draws the provided Points as a closed Linear Polygon with the provided brush at the provided thickness. - /// - /// The image this method extends. - /// The color. - /// The thickness. - /// The points. - /// The . - public static IImageProcessingContext DrawPolygon( - this IImageProcessingContext source, - Color color, - float thickness, - params PointF[] points) => - source.DrawPolygon(new SolidBrush(color), thickness, points); - - /// - /// Draws the provided Points as a closed Linear Polygon with the provided brush at the provided thickness. - /// - /// The image this method extends. - /// The options. - /// The color. - /// The thickness. - /// The points. - /// The . - public static IImageProcessingContext DrawPolygon( - this IImageProcessingContext source, - GraphicsOptions options, - Color color, - float thickness, - params PointF[] points) => - source.DrawPolygon(options, new SolidBrush(color), thickness, points); - - /// - /// Draws the provided Points as a closed Linear Polygon with the provided Pen. - /// - /// The image this method extends. - /// The pen. - /// The points. - /// The . - public static IImageProcessingContext DrawPolygon( - this IImageProcessingContext source, - IPen pen, - params PointF[] points) => - source.Draw(new GraphicsOptions(), pen, new Polygon(new LinearLineSegment(points))); - - /// - /// Draws the provided Points as a closed Linear Polygon with the provided Pen. - /// - /// The image this method extends. - /// The options. - /// The pen. - /// The points. - /// The . - public static IImageProcessingContext DrawPolygon( - this IImageProcessingContext source, - GraphicsOptions options, - IPen pen, - params PointF[] points) => - source.Draw(options, pen, new Polygon(new LinearLineSegment(points))); - } -} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Extensions/DrawRectangleExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/DrawRectangleExtensions.cs deleted file mode 100644 index b3b5dd76a..000000000 --- a/src/ImageSharp.Drawing/Processing/Extensions/DrawRectangleExtensions.cs +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.Primitives; -using SixLabors.Shapes; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// Adds extensions that allow the drawing of rectangles to the type. - /// - public static class DrawRectangleExtensions - { - /// - /// Draws the outline of the rectangle with the provided pen. - /// - /// The image this method extends. - /// The options. - /// The pen. - /// The shape. - /// The . - public static IImageProcessingContext Draw( - this IImageProcessingContext source, - GraphicsOptions options, - IPen pen, - RectangleF shape) => - source.Draw(options, pen, new RectangularPolygon(shape.X, shape.Y, shape.Width, shape.Height)); - - /// - /// Draws the outline of the rectangle with the provided pen. - /// - /// The image this method extends. - /// The pen. - /// The shape. - /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, IPen pen, RectangleF shape) => - source.Draw(new GraphicsOptions(), pen, shape); - - /// - /// Draws the outline of the rectangle with the provided brush at the provided thickness. - /// - /// The image this method extends. - /// The options. - /// The brush. - /// The thickness. - /// The shape. - /// The . - public static IImageProcessingContext Draw( - this IImageProcessingContext source, - GraphicsOptions options, - IBrush brush, - float thickness, - RectangleF shape) => - source.Draw(options, new Pen(brush, thickness), shape); - - /// - /// Draws the outline of the rectangle with the provided brush at the provided thickness. - /// - /// The image this method extends. - /// The brush. - /// The thickness. - /// The shape. - /// The . - public static IImageProcessingContext Draw( - this IImageProcessingContext source, - IBrush brush, - float thickness, - RectangleF shape) => - source.Draw(new Pen(brush, thickness), shape); - - /// - /// Draws the outline of the rectangle with the provided brush at the provided thickness. - /// - /// The image this method extends. - /// The options. - /// The color. - /// The thickness. - /// The shape. - /// The . - public static IImageProcessingContext Draw( - this IImageProcessingContext source, - GraphicsOptions options, - Color color, - float thickness, - RectangleF shape) => - source.Draw(options, new SolidBrush(color), thickness, shape); - - /// - /// Draws the outline of the rectangle with the provided brush at the provided thickness. - /// - /// The image this method extends. - /// The color. - /// The thickness. - /// The shape. - /// The . - public static IImageProcessingContext Draw( - this IImageProcessingContext source, - Color color, - float thickness, - RectangleF shape) => - source.Draw(new SolidBrush(color), thickness, shape); - } -} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Extensions/DrawTextExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/DrawTextExtensions.cs deleted file mode 100644 index 82dbb8d97..000000000 --- a/src/ImageSharp.Drawing/Processing/Extensions/DrawTextExtensions.cs +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.Fonts; -using SixLabors.ImageSharp.Processing.Processors.Text; -using SixLabors.Primitives; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// Adds extensions that allow the drawing of text to the type. - /// - public static class DrawTextExtensions - { - /// - /// Draws the text onto the the image filled via the brush. - /// - /// The image this method extends. - /// The text. - /// The font. - /// The color. - /// The location. - /// - /// The . - /// - public static IImageProcessingContext DrawText( - this IImageProcessingContext source, - string text, - Font font, - Color color, - PointF location) => - source.DrawText(new TextGraphicsOptions(), text, font, color, location); - - /// - /// Draws the text onto the the image filled via the brush. - /// - /// The image this method extends. - /// The options. - /// The text. - /// The font. - /// The color. - /// The location. - /// - /// The . - /// - public static IImageProcessingContext DrawText( - this IImageProcessingContext source, - TextGraphicsOptions options, - string text, - Font font, - Color color, - PointF location) => - source.DrawText(options, text, font, Brushes.Solid(color), null, location); - - /// - /// Draws the text onto the the image filled via the brush. - /// - /// The image this method extends. - /// The text. - /// The font. - /// The brush. - /// The location. - /// - /// The . - /// - public static IImageProcessingContext DrawText( - this IImageProcessingContext source, - string text, - Font font, - IBrush brush, - PointF location) => - source.DrawText(new TextGraphicsOptions(), text, font, brush, location); - - /// - /// Draws the text onto the the image filled via the brush. - /// - /// The image this method extends. - /// The options. - /// The text. - /// The font. - /// The brush. - /// The location. - /// - /// The . - /// - public static IImageProcessingContext DrawText( - this IImageProcessingContext source, - TextGraphicsOptions options, - string text, - Font font, - IBrush brush, - PointF location) => - source.DrawText(options, text, font, brush, null, location); - - /// - /// Draws the text onto the the image outlined via the pen. - /// - /// The image this method extends. - /// The text. - /// The font. - /// The pen. - /// The location. - /// - /// The . - /// - public static IImageProcessingContext DrawText( - this IImageProcessingContext source, - string text, - Font font, - IPen pen, - PointF location) => - source.DrawText(new TextGraphicsOptions(), text, font, pen, location); - - /// - /// Draws the text onto the the image outlined via the pen. - /// - /// The image this method extends. - /// The options. - /// The text. - /// The font. - /// The pen. - /// The location. - /// - /// The . - /// - public static IImageProcessingContext DrawText( - this IImageProcessingContext source, - TextGraphicsOptions options, - string text, - Font font, - IPen pen, - PointF location) => - source.DrawText(options, text, font, null, pen, location); - - /// - /// Draws the text onto the the image filled via the brush then outlined via the pen. - /// - /// The image this method extends. - /// The text. - /// The font. - /// The brush. - /// The pen. - /// The location. - /// - /// The . - /// - public static IImageProcessingContext DrawText( - this IImageProcessingContext source, - string text, - Font font, - IBrush brush, - IPen pen, - PointF location) => - source.DrawText(new TextGraphicsOptions(), text, font, brush, pen, location); - - /// - /// Draws the text using the default resolution of 72dpi onto the the image filled via the brush then outlined via the pen. - /// - /// The image this method extends. - /// The options. - /// The text. - /// The font. - /// The brush. - /// The pen. - /// The location. - /// - /// The . - /// - public static IImageProcessingContext DrawText( - this IImageProcessingContext source, - TextGraphicsOptions options, - string text, - Font font, - IBrush brush, - IPen pen, - PointF location) => - source.ApplyProcessor(new DrawTextProcessor(options, text, font, brush, pen, location)); - } -} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Extensions/FillPathBuilderExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/FillPathBuilderExtensions.cs deleted file mode 100644 index 030fe6ff1..000000000 --- a/src/ImageSharp.Drawing/Processing/Extensions/FillPathBuilderExtensions.cs +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; - -using SixLabors.Shapes; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// Adds extensions that allow the filling of polygons with various brushes to the type. - /// - public static class FillPathBuilderExtensions - { - /// - /// Flood fills the image in the shape of the provided polygon with the specified brush. - /// - /// The image this method extends. - /// The graphics options. - /// The brush. - /// The shape. - /// The . - public static IImageProcessingContext Fill( - this IImageProcessingContext source, - GraphicsOptions options, - IBrush brush, - Action path) - { - var pb = new PathBuilder(); - path(pb); - - return source.Fill(options, brush, pb.Build()); - } - - /// - /// Flood fills the image in the shape of the provided polygon with the specified brush. - /// - /// The image this method extends. - /// The brush. - /// The path. - /// The . - public static IImageProcessingContext Fill( - this IImageProcessingContext source, - IBrush brush, - Action path) => - source.Fill(new GraphicsOptions(), brush, path); - - /// - /// Flood fills the image in the shape of the provided polygon with the specified brush. - /// - /// The image this method extends. - /// The options. - /// The color. - /// The path. - /// The . - public static IImageProcessingContext Fill( - this IImageProcessingContext source, - GraphicsOptions options, - Color color, - Action path) => - source.Fill(options, new SolidBrush(color), path); - - /// - /// Flood fills the image in the shape of the provided polygon with the specified brush. - /// - /// The image this method extends. - /// The color. - /// The path. - /// The . - public static IImageProcessingContext Fill( - this IImageProcessingContext source, - Color color, - Action path) => - source.Fill(new SolidBrush(color), path); - } -} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Extensions/FillPathCollectionExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/FillPathCollectionExtensions.cs deleted file mode 100644 index 5d8aaf307..000000000 --- a/src/ImageSharp.Drawing/Processing/Extensions/FillPathCollectionExtensions.cs +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.Shapes; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// Adds extensions that allow the filling of collections of polygon outlines to the type. - /// - public static class FillPathCollectionExtensions - { - /// - /// Flood fills the image in the shape of the provided polygon with the specified brush. - /// - /// The image this method extends. - /// The graphics options. - /// The brush. - /// The shapes. - /// The . - public static IImageProcessingContext Fill( - this IImageProcessingContext source, - GraphicsOptions options, - IBrush brush, - IPathCollection paths) - { - foreach (IPath s in paths) - { - source.Fill(options, brush, s); - } - - return source; - } - - /// - /// Flood fills the image in the shape of the provided polygon with the specified brush. - /// - /// The image this method extends. - /// The brush. - /// The paths. - /// The . - public static IImageProcessingContext Fill( - this IImageProcessingContext source, - IBrush brush, - IPathCollection paths) => - source.Fill(new GraphicsOptions(), brush, paths); - - /// - /// Flood fills the image in the shape of the provided polygon with the specified brush. - /// - /// The image this method extends. - /// The options. - /// The color. - /// The paths. - /// The . - public static IImageProcessingContext Fill( - this IImageProcessingContext source, - GraphicsOptions options, - Color color, - IPathCollection paths) => - source.Fill(options, new SolidBrush(color), paths); - - /// - /// Flood fills the image in the shape of the provided polygon with the specified brush. - /// - /// The image this method extends. - /// The color. - /// The paths. - /// The . - public static IImageProcessingContext Fill( - this IImageProcessingContext source, - Color color, - IPathCollection paths) => - source.Fill(new SolidBrush(color), paths); - } -} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Extensions/FillPathExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/FillPathExtensions.cs deleted file mode 100644 index 4d262aa5f..000000000 --- a/src/ImageSharp.Drawing/Processing/Extensions/FillPathExtensions.cs +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.Primitives; -using SixLabors.Shapes; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// Adds extensions that allow the filling of polygon outlines to the type. - /// - public static class FillPathExtensions - { - /// - /// Flood fills the image in the shape of the provided polygon with the specified brush. - /// - /// The image this method extends. - /// The graphics options. - /// The brush. - /// The shape. - /// The . - public static IImageProcessingContext Fill( - this IImageProcessingContext source, - GraphicsOptions options, - IBrush brush, - IPath path) => - source.Fill(options, brush, new ShapeRegion(path)); - - /// - /// Flood fills the image in the shape of the provided polygon with the specified brush. - /// - /// The image this method extends. - /// The brush. - /// The path. - /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush, IPath path) => - source.Fill(new GraphicsOptions(), brush, new ShapeRegion(path)); - - /// - /// Flood fills the image in the shape of the provided polygon with the specified brush.. - /// - /// The image this method extends. - /// The options. - /// The color. - /// The path. - /// The . - public static IImageProcessingContext Fill( - this IImageProcessingContext source, - GraphicsOptions options, - Color color, - IPath path) => - source.Fill(options, new SolidBrush(color), path); - - /// - /// Flood fills the image in the shape of the provided polygon with the specified brush.. - /// - /// The image this method extends. - /// The color. - /// The path. - /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, Color color, IPath path) => - source.Fill(new SolidBrush(color), path); - } -} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Extensions/FillPolygonExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/FillPolygonExtensions.cs deleted file mode 100644 index 9262c8baa..000000000 --- a/src/ImageSharp.Drawing/Processing/Extensions/FillPolygonExtensions.cs +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.Primitives; -using SixLabors.Shapes; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// Adds extensions that allow the filling of closed linear polygons to the type. - /// - public static class FillPolygonExtensions - { - /// - /// Flood fills the image in the shape of a Linear polygon described by the points - /// - /// The image this method extends. - /// The options. - /// The brush. - /// The points. - /// The . - public static IImageProcessingContext FillPolygon( - this IImageProcessingContext source, - GraphicsOptions options, - IBrush brush, - params PointF[] points) => - source.Fill(options, brush, new Polygon(new LinearLineSegment(points))); - - /// - /// Flood fills the image in the shape of a Linear polygon described by the points - /// - /// The image this method extends. - /// The brush. - /// The points. - /// The . - public static IImageProcessingContext FillPolygon( - this IImageProcessingContext source, - IBrush brush, - params PointF[] points) => - source.Fill(brush, new Polygon(new LinearLineSegment(points))); - - /// - /// Flood fills the image in the shape of a Linear polygon described by the points - /// - /// The image this method extends. - /// The options. - /// The color. - /// The points. - /// The . - public static IImageProcessingContext FillPolygon( - this IImageProcessingContext source, - GraphicsOptions options, - Color color, - params PointF[] points) => - source.Fill(options, new SolidBrush(color), new Polygon(new LinearLineSegment(points))); - - /// - /// Flood fills the image in the shape of a Linear polygon described by the points - /// - /// The image this method extends. - /// The color. - /// The points. - /// The . - public static IImageProcessingContext FillPolygon( - this IImageProcessingContext source, - Color color, - params PointF[] points) => - source.Fill(new SolidBrush(color), new Polygon(new LinearLineSegment(points))); - } -} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Extensions/FillRectangleExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/FillRectangleExtensions.cs deleted file mode 100644 index cfe37deb2..000000000 --- a/src/ImageSharp.Drawing/Processing/Extensions/FillRectangleExtensions.cs +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.Primitives; -using SixLabors.Shapes; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// Adds extensions that allow the filling of rectangles to the type. - /// - public static class FillRectangleExtensions - { - /// - /// Flood fills the image in the shape of the provided rectangle with the specified brush. - /// - /// The image this method extends. - /// The options. - /// The brush. - /// The shape. - /// The . - public static IImageProcessingContext Fill( - this IImageProcessingContext source, - GraphicsOptions options, - IBrush brush, - RectangleF shape) => - source.Fill(options, brush, new RectangularPolygon(shape.X, shape.Y, shape.Width, shape.Height)); - - /// - /// Flood fills the image in the shape of the provided rectangle with the specified brush. - /// - /// The image this method extends. - /// The brush. - /// The shape. - /// The . - public static IImageProcessingContext - Fill(this IImageProcessingContext source, IBrush brush, RectangleF shape) => - source.Fill(brush, new RectangularPolygon(shape.X, shape.Y, shape.Width, shape.Height)); - - /// - /// Flood fills the image in the shape of the provided rectangle with the specified brush. - /// - /// The image this method extends. - /// The options. - /// The color. - /// The shape. - /// The . - public static IImageProcessingContext Fill( - this IImageProcessingContext source, - GraphicsOptions options, - Color color, - RectangleF shape) => - source.Fill(options, new SolidBrush(color), shape); - - /// - /// Flood fills the image in the shape of the provided rectangle with the specified brush. - /// - /// The image this method extends. - /// The color. - /// The shape. - /// The . - public static IImageProcessingContext - Fill(this IImageProcessingContext source, Color color, RectangleF shape) => - source.Fill(new SolidBrush(color), shape); - } -} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Extensions/FillRegionExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/FillRegionExtensions.cs deleted file mode 100644 index fbb6dbda5..000000000 --- a/src/ImageSharp.Drawing/Processing/Extensions/FillRegionExtensions.cs +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.Primitives; -using SixLabors.ImageSharp.Processing.Processors.Drawing; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// Adds extensions that allow the filling of regions with various brushes to the type. - /// - public static class FillRegionExtensions - { - /// - /// Flood fills the image with the specified brush. - /// - /// The image this method extends. - /// The details how to fill the region of interest. - /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush) => - source.Fill(new GraphicsOptions(), brush); - - /// - /// Flood fills the image with the specified color. - /// - /// The image this method extends. - /// The color. - /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, Color color) => - source.Fill(new SolidBrush(color)); - - /// - /// Flood fills the image with in the region with the specified brush. - /// - /// The image this method extends. - /// The brush. - /// The region. - /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush, Region region) => - source.Fill(new GraphicsOptions(), brush, region); - - /// - /// Flood fills the image with in the region with the specified color. - /// - /// The image this method extends. - /// The options. - /// The color. - /// The region. - /// The . - public static IImageProcessingContext Fill( - this IImageProcessingContext source, - GraphicsOptions options, - Color color, - Region region) => - source.Fill(options, new SolidBrush(color), region); - - /// - /// Flood fills the image with in the region with the specified color. - /// - /// The image this method extends. - /// The color. - /// The region. - /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, Color color, Region region) => - source.Fill(new SolidBrush(color), region); - - /// - /// Flood fills the image with in the region with the specified brush. - /// - /// The image this method extends. - /// The graphics options. - /// The brush. - /// The region. - /// The . - public static IImageProcessingContext Fill( - this IImageProcessingContext source, - GraphicsOptions options, - IBrush brush, - Region region) => - source.ApplyProcessor(new FillRegionProcessor(options, brush, region)); - - /// - /// Flood fills the image with the specified brush. - /// - /// The image this method extends. - /// The graphics options. - /// The details how to fill the region of interest. - /// The . - public static IImageProcessingContext Fill( - this IImageProcessingContext source, - GraphicsOptions options, - IBrush brush) => - source.ApplyProcessor(new FillProcessor(options, brush)); - } -} diff --git a/src/ImageSharp.Drawing/Processing/GradientBrush.cs b/src/ImageSharp.Drawing/Processing/GradientBrush.cs deleted file mode 100644 index 3be56c042..000000000 --- a/src/ImageSharp.Drawing/Processing/GradientBrush.cs +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Numerics; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Primitives; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// Base class for Gradient brushes - /// - public abstract class GradientBrush : IBrush - { - /// - /// Defines how the colors are repeated beyond the interval [0..1] - /// The gradient colors. - protected GradientBrush( - GradientRepetitionMode repetitionMode, - params ColorStop[] colorStops) - { - this.RepetitionMode = repetitionMode; - this.ColorStops = colorStops; - } - - /// - /// Gets how the colors are repeated beyond the interval [0..1]. - /// - protected GradientRepetitionMode RepetitionMode { get; } - - /// - /// Gets the list of color stops for this gradient. - /// - protected ColorStop[] ColorStops { get; } - - /// - public abstract BrushApplicator CreateApplicator( - Configuration configuration, - GraphicsOptions options, - ImageFrame source, - RectangleF region) - where TPixel : struct, IPixel; - - /// - /// Base class for gradient brush applicators - /// - internal abstract class GradientBrushApplicator : BrushApplicator - where TPixel : struct, IPixel - { - private static readonly TPixel Transparent = Color.Transparent.ToPixel(); - - private readonly ColorStop[] colorStops; - - private readonly GradientRepetitionMode repetitionMode; - - /// - /// Initializes a new instance of the class. - /// - /// The configuration instance to use when performing operations. - /// The graphics options. - /// The target image. - /// An array of color stops sorted by their position. - /// Defines if and how the gradient should be repeated. - protected GradientBrushApplicator( - Configuration configuration, - GraphicsOptions options, - ImageFrame target, - ColorStop[] colorStops, - GradientRepetitionMode repetitionMode) - : base(configuration, options, target) - { - this.colorStops = colorStops; // TODO: requires colorStops to be sorted by position - should that be checked? - this.repetitionMode = repetitionMode; - } - - /// - internal override TPixel this[int x, int y] - { - get - { - float positionOnCompleteGradient = this.PositionOnGradient(x + 0.5f, y + 0.5f); - - switch (this.repetitionMode) - { - case GradientRepetitionMode.None: - // do nothing. The following could be done, but is not necessary: - // onLocalGradient = Math.Min(0, Math.Max(1, onLocalGradient)); - break; - case GradientRepetitionMode.Repeat: - positionOnCompleteGradient %= 1; - break; - case GradientRepetitionMode.Reflect: - positionOnCompleteGradient %= 2; - if (positionOnCompleteGradient > 1) - { - positionOnCompleteGradient = 2 - positionOnCompleteGradient; - } - - break; - case GradientRepetitionMode.DontFill: - if (positionOnCompleteGradient > 1 || positionOnCompleteGradient < 0) - { - return Transparent; - } - - break; - default: - throw new ArgumentOutOfRangeException(); - } - - (ColorStop from, ColorStop to) = this.GetGradientSegment(positionOnCompleteGradient); - - if (from.Color.Equals(to.Color)) - { - return from.Color.ToPixel(); - } - else - { - float onLocalGradient = (positionOnCompleteGradient - from.Ratio) / (to.Ratio - from.Ratio); - return new Color(Vector4.Lerp((Vector4)from.Color, (Vector4)to.Color, onLocalGradient)).ToPixel(); - } - } - } - - /// - /// calculates the position on the gradient for a given point. - /// This method is abstract as it's content depends on the shape of the gradient. - /// - /// The x-coordinate of the point. - /// The y-coordinate of the point. - /// - /// The position the given point has on the gradient. - /// The position is not bound to the [0..1] interval. - /// Values outside of that interval may be treated differently, - /// e.g. for the enum. - /// - protected abstract float PositionOnGradient(float x, float y); - - private (ColorStop from, ColorStop to) GetGradientSegment( - float positionOnCompleteGradient) - { - ColorStop localGradientFrom = this.colorStops[0]; - ColorStop localGradientTo = default; - - // TODO: ensure colorStops has at least 2 items (technically 1 would be okay, but that's no gradient) - foreach (ColorStop colorStop in this.colorStops) - { - localGradientTo = colorStop; - - if (colorStop.Ratio > positionOnCompleteGradient) - { - // we're done here, so break it! - break; - } - - localGradientFrom = localGradientTo; - } - - return (localGradientFrom, localGradientTo); - } - } - } -} diff --git a/src/ImageSharp.Drawing/Processing/GradientRepetitionMode.cs b/src/ImageSharp.Drawing/Processing/GradientRepetitionMode.cs deleted file mode 100644 index 6aed8a030..000000000 --- a/src/ImageSharp.Drawing/Processing/GradientRepetitionMode.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// Modes to repeat a gradient. - /// - public enum GradientRepetitionMode - { - /// - /// don't repeat, keep the color of start and end beyond those points stable. - /// - None, - - /// - /// Repeat the gradient. - /// If it's a black-white gradient, with Repeat it will be Black->{gray}->White|Black->{gray}->White|... - /// - Repeat, - - /// - /// Reflect the gradient. - /// Similar to , but each other repetition uses inverse order of s. - /// Used on a Black-White gradient, Reflect leads to Black->{gray}->White->{gray}->White... - /// - Reflect, - - /// - /// With DontFill a gradient does not touch any pixel beyond it's borders. - /// For the this is beyond the orthogonal through start and end, - /// TODO For the cref="PolygonalGradientBrush" it's outside the polygon, - /// For and it's beyond 1.0. - /// - DontFill - } -} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/IBrush.cs b/src/ImageSharp.Drawing/Processing/IBrush.cs deleted file mode 100644 index f4c7ef7cb..000000000 --- a/src/ImageSharp.Drawing/Processing/IBrush.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Primitives; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// Brush represents a logical configuration of a brush which can be used to source pixel colors - /// - /// - /// A brush is a simple class that will return an that will perform the - /// logic for retrieving pixel values for specific locations. - /// - public interface IBrush - { - /// - /// Creates the applicator for this brush. - /// - /// The pixel type. - /// The configuration instance to use when performing operations. - /// The graphic options. - /// The source image. - /// The region the brush will be applied to. - /// - /// The for this brush. - /// - /// - /// The when being applied to things like shapes would usually be the - /// bounding box of the shape not necessarily the bounds of the whole image. - /// - BrushApplicator CreateApplicator( - Configuration configuration, - GraphicsOptions options, - ImageFrame source, - RectangleF region) - where TPixel : struct, IPixel; - } -} diff --git a/src/ImageSharp.Drawing/Processing/IPen.cs b/src/ImageSharp.Drawing/Processing/IPen.cs deleted file mode 100644 index 0efcfc108..000000000 --- a/src/ImageSharp.Drawing/Processing/IPen.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// Interface representing the pattern and size of the stroke to apply with a Pen. - /// - public interface IPen - { - /// - /// Gets the stroke fill. - /// - IBrush StrokeFill { get; } - - /// - /// Gets the width to apply to the stroke - /// - float StrokeWidth { get; } - - /// - /// Gets the stoke pattern. - /// - ReadOnlySpan StrokePattern { get; } - } -} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/ImageBrush.cs b/src/ImageSharp.Drawing/Processing/ImageBrush.cs deleted file mode 100644 index e38614070..000000000 --- a/src/ImageSharp.Drawing/Processing/ImageBrush.cs +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Buffers; - -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Primitives; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// Provides an implementation of an image brush for painting images within areas. - /// - public class ImageBrush : IBrush - { - /// - /// The image to paint. - /// - private readonly Image image; - - /// - /// Initializes a new instance of the class. - /// - /// The image. - public ImageBrush(Image image) - { - this.image = image; - } - - /// - public BrushApplicator CreateApplicator( - Configuration configuration, - GraphicsOptions options, - ImageFrame source, - RectangleF region) - where TPixel : struct, IPixel - { - if (this.image is Image specificImage) - { - return new ImageBrushApplicator(configuration, options, source, specificImage, region, false); - } - - specificImage = this.image.CloneAs(); - - return new ImageBrushApplicator(configuration, options, source, specificImage, region, true); - } - - /// - /// The image brush applicator. - /// - private class ImageBrushApplicator : BrushApplicator - where TPixel : struct, IPixel - { - private ImageFrame sourceFrame; - - private Image sourceImage; - - private readonly bool shouldDisposeImage; - - /// - /// The y-length. - /// - private readonly int yLength; - - /// - /// The x-length. - /// - private readonly int xLength; - - /// - /// The Y offset. - /// - private readonly int offsetY; - - /// - /// The X offset. - /// - private readonly int offsetX; - - private bool isDisposed; - - /// - /// Initializes a new instance of the class. - /// - /// The configuration instance to use when performing operations. - /// The graphics options. - /// The target image. - /// The image. - /// The region. - /// Whether to dispose the image on disposal of the applicator. - public ImageBrushApplicator( - Configuration configuration, - GraphicsOptions options, - ImageFrame target, - Image image, - RectangleF region, - bool shouldDisposeImage) - : base(configuration, options, target) - { - this.sourceImage = image; - this.sourceFrame = image.Frames.RootFrame; - this.shouldDisposeImage = shouldDisposeImage; - this.xLength = image.Width; - this.yLength = image.Height; - this.offsetY = (int)MathF.Max(MathF.Floor(region.Top), 0); - this.offsetX = (int)MathF.Max(MathF.Floor(region.Left), 0); - } - - /// - internal override TPixel this[int x, int y] - { - get - { - int srcX = (x - this.offsetX) % this.xLength; - int srcY = (y - this.offsetY) % this.yLength; - return this.sourceFrame[srcX, srcY]; - } - } - - /// - protected override void Dispose(bool disposing) - { - if (this.isDisposed) - { - return; - } - - if (disposing && this.shouldDisposeImage) - { - this.sourceImage?.Dispose(); - } - - this.sourceImage = null; - this.sourceFrame = null; - this.isDisposed = true; - } - - /// - internal override void Apply(Span scanline, int x, int y) - { - // Create a span for colors - using (IMemoryOwner amountBuffer = this.Target.MemoryAllocator.Allocate(scanline.Length)) - using (IMemoryOwner overlay = this.Target.MemoryAllocator.Allocate(scanline.Length)) - { - Span amountSpan = amountBuffer.Memory.Span; - Span overlaySpan = overlay.Memory.Span; - - int sourceY = (y - this.offsetY) % this.yLength; - int offsetX = x - this.offsetX; - Span sourceRow = this.sourceFrame.GetPixelRowSpan(sourceY); - - for (int i = 0; i < scanline.Length; i++) - { - amountSpan[i] = scanline[i] * this.Options.BlendPercentage; - - int sourceX = (i + offsetX) % this.xLength; - overlaySpan[i] = sourceRow[sourceX]; - } - - Span destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length); - this.Blender.Blend( - this.Configuration, - destinationRow, - destinationRow, - overlaySpan, - amountSpan); - } - } - } - } -} diff --git a/src/ImageSharp.Drawing/Processing/LinearGradientBrush.cs b/src/ImageSharp.Drawing/Processing/LinearGradientBrush.cs deleted file mode 100644 index 044bee72c..000000000 --- a/src/ImageSharp.Drawing/Processing/LinearGradientBrush.cs +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Primitives; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// Provides an implementation of a brush for painting linear gradients within areas. - /// Supported right now: - /// - a set of colors in relative distances to each other. - /// - public sealed class LinearGradientBrush : GradientBrush - { - private readonly PointF p1; - - private readonly PointF p2; - - /// - /// Initializes a new instance of the class. - /// - /// Start point - /// End point - /// defines how colors are repeated. - /// - public LinearGradientBrush( - PointF p1, - PointF p2, - GradientRepetitionMode repetitionMode, - params ColorStop[] colorStops) - : base(repetitionMode, colorStops) - { - this.p1 = p1; - this.p2 = p2; - } - - /// - public override BrushApplicator CreateApplicator( - Configuration configuration, - GraphicsOptions options, - ImageFrame source, - RectangleF region) => - new LinearGradientBrushApplicator( - configuration, - options, - source, - this.p1, - this.p2, - this.ColorStops, - this.RepetitionMode); - - /// - /// The linear gradient brush applicator. - /// - private sealed class LinearGradientBrushApplicator : GradientBrushApplicator - where TPixel : struct, IPixel - { - private readonly PointF start; - - private readonly PointF end; - - /// - /// the vector along the gradient, x component - /// - private readonly float alongX; - - /// - /// the vector along the gradient, y component - /// - private readonly float alongY; - - /// - /// the vector perpendicular to the gradient, y component - /// - private readonly float acrossY; - - /// - /// the vector perpendicular to the gradient, x component - /// - private readonly float acrossX; - - /// - /// the result of ^2 + ^2 - /// - private readonly float alongsSquared; - - /// - /// the length of the defined gradient (between source and end) - /// - private readonly float length; - - /// - /// Initializes a new instance of the class. - /// - /// The configuration instance to use when performing operations. - /// The graphics options. - /// The source image. - /// The start point of the gradient. - /// The end point of the gradient. - /// A tuple list of colors and their respective position between 0 and 1 on the line. - /// Defines how the gradient colors are repeated. - public LinearGradientBrushApplicator( - Configuration configuration, - GraphicsOptions options, - ImageFrame source, - PointF start, - PointF end, - ColorStop[] colorStops, - GradientRepetitionMode repetitionMode) - : base(configuration, options, source, colorStops, repetitionMode) - { - this.start = start; - this.end = end; - - // the along vector: - this.alongX = this.end.X - this.start.X; - this.alongY = this.end.Y - this.start.Y; - - // the cross vector: - this.acrossX = this.alongY; - this.acrossY = -this.alongX; - - // some helpers: - this.alongsSquared = (this.alongX * this.alongX) + (this.alongY * this.alongY); - this.length = MathF.Sqrt(this.alongsSquared); - } - - protected override float PositionOnGradient(float x, float y) - { - if (this.acrossX == 0) - { - return (x - this.start.X) / (this.end.X - this.start.X); - } - else if (this.acrossY == 0) - { - return (y - this.start.Y) / (this.end.Y - this.start.Y); - } - else - { - float deltaX = x - this.start.X; - float deltaY = y - this.start.Y; - float k = ((this.alongY * deltaX) - (this.alongX * deltaY)) / this.alongsSquared; - - // point on the line: - float x4 = x - (k * this.alongY); - float y4 = y + (k * this.alongX); - - // get distance from (x4,y4) to start - float distance = MathF.Sqrt(MathF.Pow(x4 - this.start.X, 2) + MathF.Pow(y4 - this.start.Y, 2)); - - // get and return ratio - return distance / this.length; - } - } - } - } -} diff --git a/src/ImageSharp.Drawing/Processing/PathGradientBrush.cs b/src/ImageSharp.Drawing/Processing/PathGradientBrush.cs deleted file mode 100644 index 126567899..000000000 --- a/src/ImageSharp.Drawing/Processing/PathGradientBrush.cs +++ /dev/null @@ -1,309 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Buffers; -using System.Collections.Generic; -using System.Linq; -using System.Numerics; - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Memory; -using SixLabors.Primitives; -using SixLabors.Shapes; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// Provides an implementation of a brush for painting gradients between multiple color positions in 2D coordinates. - /// It works similarly with the class in System.Drawing.Drawing2D of the same name. - /// - public sealed class PathGradientBrush : IBrush - { - private readonly IList edges; - - private readonly Color centerColor; - - /// - /// Initializes a new instance of the class. - /// - /// Points that constitute a polygon that represents the gradient area. - /// Array of colors that correspond to each point in the polygon. - /// Color at the center of the gradient area to which the other colors converge. - public PathGradientBrush(PointF[] points, Color[] colors, Color centerColor) - { - if (points == null) - { - throw new ArgumentNullException(nameof(points)); - } - - if (points.Length < 3) - { - throw new ArgumentOutOfRangeException( - nameof(points), - "There must be at least 3 lines to construct a path gradient brush."); - } - - if (colors == null) - { - throw new ArgumentNullException(nameof(colors)); - } - - if (colors.Length == 0) - { - throw new ArgumentOutOfRangeException( - nameof(colors), - "One or more color is needed to construct a path gradient brush."); - } - - int size = points.Length; - - var lines = new ILineSegment[size]; - - for (int i = 0; i < size; i++) - { - lines[i] = new LinearLineSegment(points[i % size], points[(i + 1) % size]); - } - - this.centerColor = centerColor; - - Color ColorAt(int index) => colors[index % colors.Length]; - - this.edges = lines.Select(s => new Path(s)) - .Select((path, i) => new Edge(path, ColorAt(i), ColorAt(i + 1))).ToList(); - } - - /// - /// Initializes a new instance of the class. - /// - /// Points that constitute a polygon that represents the gradient area. - /// Array of colors that correspond to each point in the polygon. - public PathGradientBrush(PointF[] points, Color[] colors) - : this(points, colors, CalculateCenterColor(colors)) - { - } - - /// - public BrushApplicator CreateApplicator( - Configuration configuration, - GraphicsOptions options, - ImageFrame source, - RectangleF region) - where TPixel : struct, IPixel - { - return new PathGradientBrushApplicator(configuration, options, source, this.edges, this.centerColor); - } - - private static Color CalculateCenterColor(Color[] colors) - { - if (colors == null) - { - throw new ArgumentNullException(nameof(colors)); - } - - if (colors.Length == 0) - { - throw new ArgumentOutOfRangeException( - nameof(colors), - "One or more color is needed to construct a path gradient brush."); - } - - return new Color(colors.Select(c => (Vector4)c).Aggregate((p1, p2) => p1 + p2) / colors.Length); - } - - private static float DistanceBetween(PointF p1, PointF p2) => ((Vector2)(p2 - p1)).Length(); - - private struct Intersection - { - public Intersection(PointF point, float distance) - { - this.Point = point; - this.Distance = distance; - } - - public PointF Point { get; } - - public float Distance { get; } - } - - /// - /// An edge of the polygon that represents the gradient area. - /// - private class Edge - { - private readonly Path path; - - private readonly float length; - - public Edge(Path path, Color startColor, Color endColor) - { - this.path = path; - - Vector2[] points = path.LineSegments.SelectMany(s => s.Flatten()).Select(p => (Vector2)p).ToArray(); - - this.Start = points[0]; - this.StartColor = (Vector4)startColor; - - this.End = points.Last(); - this.EndColor = (Vector4)endColor; - - this.length = DistanceBetween(this.End, this.Start); - } - - public PointF Start { get; } - - public Vector4 StartColor { get; } - - public PointF End { get; } - - public Vector4 EndColor { get; } - - public Intersection? FindIntersection(PointF start, PointF end, MemoryAllocator allocator) - { - // TODO: The number of max intersections is upper bound to the number of nodes of the path. - // Normally these numbers would be small and could potentially be stackalloc rather than pooled. - // Investigate performance beifit of checking length and choosing approach. - using (IMemoryOwner memory = allocator.Allocate(this.path.MaxIntersections)) - { - Span buffer = memory.Memory.Span; - int intersections = this.path.FindIntersections(start, end, buffer); - - if (intersections == 0) - { - return null; - } - - buffer = buffer.Slice(0, intersections); - - PointF minPoint = buffer[0]; - var min = new Intersection(minPoint, ((Vector2)(minPoint - start)).LengthSquared()); - for (int i = 1; i < buffer.Length; i++) - { - PointF point = buffer[i]; - var current = new Intersection(point, ((Vector2)(point - start)).LengthSquared()); - - if (min.Distance > current.Distance) - { - min = current; - } - } - - return min; - } - } - - public Vector4 ColorAt(float distance) - { - float ratio = this.length > 0 ? distance / this.length : 0; - - return Vector4.Lerp(this.StartColor, this.EndColor, ratio); - } - - public Vector4 ColorAt(PointF point) => this.ColorAt(DistanceBetween(point, this.Start)); - } - - /// - /// The path gradient brush applicator. - /// - private class PathGradientBrushApplicator : BrushApplicator - where TPixel : struct, IPixel - { - private readonly PointF center; - - private readonly Vector4 centerColor; - - private readonly float maxDistance; - - private readonly IList edges; - - private readonly TPixel centerPixel; - - private readonly TPixel transparentPixel; - - /// - /// Initializes a new instance of the class. - /// - /// The configuration instance to use when performing operations. - /// The graphics options. - /// The source image. - /// Edges of the polygon. - /// Color at the center of the gradient area to which the other colors converge. - public PathGradientBrushApplicator( - Configuration configuration, - GraphicsOptions options, - ImageFrame source, - IList edges, - Color centerColor) - : base(configuration, options, source) - { - this.edges = edges; - PointF[] points = edges.Select(s => s.Start).ToArray(); - - this.center = points.Aggregate((p1, p2) => p1 + p2) / edges.Count; - this.centerColor = (Vector4)centerColor; - this.centerPixel = centerColor.ToPixel(); - - this.maxDistance = points.Select(p => (Vector2)(p - this.center)).Max(d => d.Length()); - - this.transparentPixel = Color.Transparent.ToPixel(); - } - - /// - internal override TPixel this[int x, int y] - { - get - { - var point = new PointF(x, y); - - if (point == this.center) - { - return this.centerPixel; - } - - var direction = Vector2.Normalize(point - this.center); - PointF end = point + (PointF)(direction * this.maxDistance); - - (Edge edge, Intersection? info) = this.FindIntersection(point, end); - - if (!info.HasValue) - { - return this.transparentPixel; - } - - PointF intersection = info.Value.Point; - Vector4 edgeColor = edge.ColorAt(intersection); - - float length = DistanceBetween(intersection, this.center); - float ratio = length > 0 ? DistanceBetween(intersection, point) / length : 0; - - var color = Vector4.Lerp(edgeColor, this.centerColor, ratio); - - return new Color(color).ToPixel(); - } - } - - private (Edge edge, Intersection? info) FindIntersection(PointF start, PointF end) - { - (Edge edge, Intersection? info) closest = default; - - MemoryAllocator allocator = this.Target.MemoryAllocator; - foreach (Edge edge in this.edges) - { - Intersection? intersection = edge.FindIntersection(start, end, allocator); - - if (!intersection.HasValue) - { - continue; - } - - if (closest.info == null || closest.info.Value.Distance > intersection.Value.Distance) - { - closest = (edge, intersection); - } - } - - return closest; - } - } - } -} diff --git a/src/ImageSharp.Drawing/Processing/PatternBrush.cs b/src/ImageSharp.Drawing/Processing/PatternBrush.cs deleted file mode 100644 index 726df5a79..000000000 --- a/src/ImageSharp.Drawing/Processing/PatternBrush.cs +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Buffers; -using System.Numerics; -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Primitives; -using SixLabors.Memory; -using SixLabors.Primitives; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// Provides an implementation of a pattern brush for painting patterns. - /// - /// - /// The patterns that are used to create a custom pattern brush are made up of a repeating matrix of flags, - /// where each flag denotes whether to draw the foreground color or the background color. - /// so to create a new bool[,] with your flags - /// - /// For example if you wanted to create a diagonal line that repeat every 4 pixels you would use a pattern like so - /// 1000 - /// 0100 - /// 0010 - /// 0001 - /// - /// - /// or you want a horizontal stripe which is 3 pixels apart you would use a pattern like - /// 1 - /// 0 - /// 0 - /// - /// - public class PatternBrush : IBrush - { - /// - /// The pattern. - /// - private readonly DenseMatrix pattern; - private readonly DenseMatrix patternVector; - - /// - /// Initializes a new instance of the class. - /// - /// Color of the fore. - /// Color of the back. - /// The pattern. - public PatternBrush(Color foreColor, Color backColor, bool[,] pattern) - : this(foreColor, backColor, new DenseMatrix(pattern)) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// Color of the fore. - /// Color of the back. - /// The pattern. - internal PatternBrush(Color foreColor, Color backColor, in DenseMatrix pattern) - { - var foreColorVector = (Vector4)foreColor; - var backColorVector = (Vector4)backColor; - this.pattern = new DenseMatrix(pattern.Columns, pattern.Rows); - this.patternVector = new DenseMatrix(pattern.Columns, pattern.Rows); - for (int i = 0; i < pattern.Data.Length; i++) - { - if (pattern.Data[i]) - { - this.pattern.Data[i] = foreColor; - this.patternVector.Data[i] = foreColorVector; - } - else - { - this.pattern.Data[i] = backColor; - this.patternVector.Data[i] = backColorVector; - } - } - } - - /// - /// Initializes a new instance of the class. - /// - /// The brush. - internal PatternBrush(PatternBrush brush) - { - this.pattern = brush.pattern; - this.patternVector = brush.patternVector; - } - - /// - public BrushApplicator CreateApplicator( - Configuration configuration, - GraphicsOptions options, - ImageFrame source, - RectangleF region) - where TPixel : struct, IPixel => - new PatternBrushApplicator( - configuration, - options, - source, - this.pattern.ToPixelMatrix(configuration)); - - /// - /// The pattern brush applicator. - /// - private class PatternBrushApplicator : BrushApplicator - where TPixel : struct, IPixel - { - /// - /// The pattern. - /// - private readonly DenseMatrix pattern; - - /// - /// Initializes a new instance of the class. - /// - /// The configuration instance to use when performing operations. - /// The graphics options. - /// The source image. - /// The pattern. - public PatternBrushApplicator( - Configuration configuration, - GraphicsOptions options, - ImageFrame source, - in DenseMatrix pattern) - : base(configuration, options, source) - { - this.pattern = pattern; - } - - /// - internal override TPixel this[int x, int y] - { - get - { - x %= this.pattern.Columns; - y %= this.pattern.Rows; - - // 2d array index at row/column - return this.pattern[y, x]; - } - } - - /// - internal override void Apply(Span scanline, int x, int y) - { - int patternY = y % this.pattern.Rows; - MemoryAllocator memoryAllocator = this.Target.MemoryAllocator; - - using (IMemoryOwner amountBuffer = memoryAllocator.Allocate(scanline.Length)) - using (IMemoryOwner overlay = memoryAllocator.Allocate(scanline.Length)) - { - Span amountSpan = amountBuffer.Memory.Span; - Span overlaySpan = overlay.Memory.Span; - - for (int i = 0; i < scanline.Length; i++) - { - amountSpan[i] = NumberUtils.ClampFloat(scanline[i] * this.Options.BlendPercentage, 0, 1F); - - int patternX = (x + i) % this.pattern.Columns; - overlaySpan[i] = this.pattern[patternY, patternX]; - } - - Span destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length); - this.Blender.Blend( - this.Configuration, - destinationRow, - destinationRow, - overlaySpan, - amountSpan); - } - } - } - } -} diff --git a/src/ImageSharp.Drawing/Processing/Pen.cs b/src/ImageSharp.Drawing/Processing/Pen.cs deleted file mode 100644 index ebad687d5..000000000 --- a/src/ImageSharp.Drawing/Processing/Pen.cs +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// Provides a pen that can apply a pattern to a line with a set brush and thickness - /// - /// - /// The pattern will be in to the form of new float[]{ 1f, 2f, 0.5f} this will be - /// converted into a pattern that is 3.5 times longer that the width with 3 sections - /// section 1 will be width long (making a square) and will be filled by the brush - /// section 2 will be width * 2 long and will be empty - /// section 3 will be width/2 long and will be filled - /// the the pattern will immediately repeat without gap. - /// - public class Pen : IPen - { - private readonly float[] pattern; - - /// - /// Initializes a new instance of the class. - /// - /// The color. - /// The width. - /// The pattern. - public Pen(Color color, float width, float[] pattern) - : this(new SolidBrush(color), width, pattern) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The brush. - /// The width. - /// The pattern. - public Pen(IBrush brush, float width, float[] pattern) - { - this.StrokeFill = brush; - this.StrokeWidth = width; - this.pattern = pattern; - } - - /// - /// Initializes a new instance of the class. - /// - /// The color. - /// The width. - public Pen(Color color, float width) - : this(new SolidBrush(color), width) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The brush. - /// The width. - public Pen(IBrush brush, float width) - : this(brush, width, Pens.EmptyPattern) - { - } - - /// - public IBrush StrokeFill { get; } - - /// - public float StrokeWidth { get; } - - /// - public ReadOnlySpan StrokePattern => this.pattern; - } -} diff --git a/src/ImageSharp.Drawing/Processing/Pens.cs b/src/ImageSharp.Drawing/Processing/Pens.cs deleted file mode 100644 index e60b5b6c7..000000000 --- a/src/ImageSharp.Drawing/Processing/Pens.cs +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// Contains a collection of common Pen styles - /// - public static class Pens - { - private static readonly float[] DashDotPattern = { 3f, 1f, 1f, 1f }; - private static readonly float[] DashDotDotPattern = { 3f, 1f, 1f, 1f, 1f, 1f }; - private static readonly float[] DottedPattern = { 1f, 1f }; - private static readonly float[] DashedPattern = { 3f, 1f }; - internal static readonly float[] EmptyPattern = new float[0]; - - /// - /// Create a solid pen with out any drawing patterns - /// - /// The color. - /// The width. - /// The Pen - public static Pen Solid(Color color, float width) => new Pen(color, width); - - /// - /// Create a solid pen with out any drawing patterns - /// - /// The brush. - /// The width. - /// The Pen - public static Pen Solid(IBrush brush, float width) => new Pen(brush, width); - - /// - /// Create a pen with a 'Dash' drawing patterns - /// - /// The color. - /// The width. - /// The Pen - public static Pen Dash(Color color, float width) => new Pen(color, width, DashedPattern); - - /// - /// Create a pen with a 'Dash' drawing patterns - /// - /// The brush. - /// The width. - /// The Pen - public static Pen Dash(IBrush brush, float width) => new Pen(brush, width, DashedPattern); - - /// - /// Create a pen with a 'Dot' drawing patterns - /// - /// The color. - /// The width. - /// The Pen - public static Pen Dot(Color color, float width) => new Pen(color, width, DottedPattern); - - /// - /// Create a pen with a 'Dot' drawing patterns - /// - /// The brush. - /// The width. - /// The Pen - public static Pen Dot(IBrush brush, float width) => new Pen(brush, width, DottedPattern); - - /// - /// Create a pen with a 'Dash Dot' drawing patterns - /// - /// The color. - /// The width. - /// The Pen - public static Pen DashDot(Color color, float width) => new Pen(color, width, DashDotPattern); - - /// - /// Create a pen with a 'Dash Dot' drawing patterns - /// - /// The brush. - /// The width. - /// The Pen - public static Pen DashDot(IBrush brush, float width) => new Pen(brush, width, DashDotPattern); - - /// - /// Create a pen with a 'Dash Dot Dot' drawing patterns - /// - /// The color. - /// The width. - /// The Pen - public static Pen DashDotDot(Color color, float width) => new Pen(color, width, DashDotDotPattern); - - /// - /// Create a pen with a 'Dash Dot Dot' drawing patterns - /// - /// The brush. - /// The width. - /// The Pen - public static Pen DashDotDot(IBrush brush, float width) => new Pen(brush, width, DashDotDotPattern); - } -} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs deleted file mode 100644 index c94e0c179..000000000 --- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Primitives; - -namespace SixLabors.ImageSharp.Processing.Processors.Drawing -{ - /// - /// Defines a processor to fill an with the given - /// using blending defined by the given . - /// - public class FillProcessor : IImageProcessor - { - /// - /// Initializes a new instance of the class. - /// - /// The defining how to blend the brush pixels over the image pixels. - /// The brush to use for filling. - public FillProcessor(GraphicsOptions options, IBrush brush) - { - this.Brush = brush; - this.Options = options; - } - - /// - /// Gets the used for filling the destination image. - /// - public IBrush Brush { get; } - - /// - /// Gets the defining how to blend the brush pixels over the image pixels. - /// - public GraphicsOptions Options { get; } - - /// - public IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle) - where TPixel : struct, IPixel - => new FillProcessor(configuration, this, source, sourceRectangle); - } -} diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor{TPixel}.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor{TPixel}.cs deleted file mode 100644 index ca639cd14..000000000 --- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor{TPixel}.cs +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Buffers; - -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Advanced.ParallelUtils; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Primitives; - -namespace SixLabors.ImageSharp.Processing.Processors.Drawing -{ - /// - /// Using the brush as a source of pixels colors blends the brush color with source. - /// - /// The pixel format. - internal class FillProcessor : ImageProcessor - where TPixel : struct, IPixel - { - private readonly FillProcessor definition; - - public FillProcessor(Configuration configuration, FillProcessor definition, Image source, Rectangle sourceRectangle) - : base(configuration, source, sourceRectangle) - { - this.definition = definition; - } - - /// - protected override void OnFrameApply(ImageFrame source) - { - Rectangle sourceRectangle = this.SourceRectangle; - Configuration configuration = this.Configuration; - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - int startY = sourceRectangle.Y; - int endY = sourceRectangle.Bottom; - - // Align start/end positions. - int minX = Math.Max(0, startX); - int maxX = Math.Min(source.Width, endX); - int minY = Math.Max(0, startY); - int maxY = Math.Min(source.Height, endY); - - int width = maxX - minX; - - var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); - - IBrush brush = this.definition.Brush; - GraphicsOptions options = this.definition.Options; - - // If there's no reason for blending, then avoid it. - if (this.IsSolidBrushWithoutBlending(out SolidBrush solidBrush)) - { - ParallelExecutionSettings parallelSettings = ParallelExecutionSettings.FromConfiguration(configuration) - .MultiplyMinimumPixelsPerTask(4); - - TPixel colorPixel = solidBrush.Color.ToPixel(); - - ParallelHelper.IterateRows( - workingRect, - parallelSettings, - rows => - { - for (int y = rows.Min; y < rows.Max; y++) - { - source.GetPixelRowSpan(y).Slice(minX, width).Fill(colorPixel); - } - }); - } - else - { - // Reset offset if necessary. - if (minX > 0) - { - startX = 0; - } - - if (minY > 0) - { - startY = 0; - } - - using (IMemoryOwner amount = source.MemoryAllocator.Allocate(width)) - using (BrushApplicator applicator = brush.CreateApplicator( - configuration, - options, - source, - sourceRectangle)) - { - amount.Memory.Span.Fill(1F); - - ParallelHelper.IterateRows( - workingRect, - configuration, - rows => - { - for (int y = rows.Min; y < rows.Max; y++) - { - int offsetY = y - startY; - int offsetX = minX - startX; - - applicator.Apply(amount.Memory.Span, offsetX, offsetY); - } - }); - } - } - } - - private bool IsSolidBrushWithoutBlending(out SolidBrush solidBrush) - { - solidBrush = this.definition.Brush as SolidBrush; - - if (solidBrush is null) - { - return false; - } - - return this.definition.Options.IsOpaqueColorWithoutBlending(solidBrush.Color); - } - } -} diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs deleted file mode 100644 index 6cfeb785c..000000000 --- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Primitives; -using SixLabors.Primitives; - -namespace SixLabors.ImageSharp.Processing.Processors.Drawing -{ - /// - /// Defines a processor to fill pixels withing a given - /// with the given and blending defined by the given . - /// - public class FillRegionProcessor : IImageProcessor - { - /// - /// Initializes a new instance of the class. - /// - /// The graphics options. - /// The details how to fill the region of interest. - /// The region of interest to be filled. - public FillRegionProcessor(GraphicsOptions options, IBrush brush, Region region) - { - this.Region = region; - this.Brush = brush; - this.Options = options; - } - - /// - /// Gets the used for filling the destination image. - /// - public IBrush Brush { get; } - - /// - /// Gets the region that this processor applies to. - /// - public Region Region { get; } - - /// - /// Gets the defining how to blend the brush pixels over the image pixels. - /// - public GraphicsOptions Options { get; } - - /// - public IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle) - where TPixel : struct, IPixel - => new FillRegionProcessor(configuration, this, source, sourceRectangle); - } -} diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor{TPixel}.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor{TPixel}.cs deleted file mode 100644 index 7d632ad23..000000000 --- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor{TPixel}.cs +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Buffers; - -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Primitives; -using SixLabors.ImageSharp.Utils; -using SixLabors.Primitives; - -namespace SixLabors.ImageSharp.Processing.Processors.Drawing -{ - /// - /// Using a brush and a shape fills shape with contents of brush the - /// - /// The type of the color. - /// - internal class FillRegionProcessor : ImageProcessor - where TPixel : struct, IPixel - { - private readonly FillRegionProcessor definition; - - public FillRegionProcessor(Configuration configuration, FillRegionProcessor definition, Image source, Rectangle sourceRectangle) - : base(configuration, source, sourceRectangle) - { - this.definition = definition; - } - - /// - protected override void OnFrameApply(ImageFrame source) - { - Configuration configuration = this.Configuration; - GraphicsOptions options = this.definition.Options; - IBrush brush = this.definition.Brush; - Region region = this.definition.Region; - Rectangle rect = region.Bounds; - - // Align start/end positions. - int minX = Math.Max(0, rect.Left); - int maxX = Math.Min(source.Width, rect.Right); - int minY = Math.Max(0, rect.Top); - int maxY = Math.Min(source.Height, rect.Bottom); - if (minX >= maxX) - { - return; // no effect inside image; - } - - if (minY >= maxY) - { - return; // no effect inside image; - } - - int maxIntersections = region.MaxIntersections; - float subpixelCount = 4; - - // we need to offset the pixel grid to account for when we outline a path. - // basically if the line is [1,2] => [3,2] then when outlining at 1 we end up with a region of [0.5,1.5],[1.5, 1.5],[3.5,2.5],[2.5,2.5] - // and this can cause missed fills when not using antialiasing.so we offset the pixel grid by 0.5 in the x & y direction thus causing the# - // region to align with the pixel grid. - float offset = 0.5f; - if (options.Antialias) - { - offset = 0f; // we are antialiasing skip offsetting as real antialiasing should take care of offset. - subpixelCount = options.AntialiasSubpixelDepth; - if (subpixelCount < 4) - { - subpixelCount = 4; - } - } - - using (BrushApplicator applicator = brush.CreateApplicator(configuration, options, source, rect)) - { - int scanlineWidth = maxX - minX; - using (IMemoryOwner bBuffer = source.MemoryAllocator.Allocate(maxIntersections)) - using (IMemoryOwner bScanline = source.MemoryAllocator.Allocate(scanlineWidth)) - { - bool scanlineDirty = true; - float subpixelFraction = 1f / subpixelCount; - float subpixelFractionPoint = subpixelFraction / subpixelCount; - - Span buffer = bBuffer.Memory.Span; - Span scanline = bScanline.Memory.Span; - - bool isSolidBrushWithoutBlending = this.IsSolidBrushWithoutBlending(out SolidBrush solidBrush); - TPixel solidBrushColor = isSolidBrushWithoutBlending ? solidBrush.Color.ToPixel() : default; - - for (int y = minY; y < maxY; y++) - { - if (scanlineDirty) - { - scanline.Clear(); - scanlineDirty = false; - } - - float yPlusOne = y + 1; - for (float subPixel = y; subPixel < yPlusOne; subPixel += subpixelFraction) - { - int pointsFound = region.Scan(subPixel + offset, buffer, configuration); - if (pointsFound == 0) - { - // nothing on this line, skip - continue; - } - - QuickSort.Sort(buffer.Slice(0, pointsFound)); - - for (int point = 0; point < pointsFound && point < buffer.Length - 1; point += 2) - { - // points will be paired up - float scanStart = buffer[point] - minX; - float scanEnd = buffer[point + 1] - minX; - int startX = (int)MathF.Floor(scanStart + offset); - int endX = (int)MathF.Floor(scanEnd + offset); - - if (startX >= 0 && startX < scanline.Length) - { - for (float x = scanStart; x < startX + 1; x += subpixelFraction) - { - scanline[startX] += subpixelFractionPoint; - scanlineDirty = true; - } - } - - if (endX >= 0 && endX < scanline.Length) - { - for (float x = endX; x < scanEnd; x += subpixelFraction) - { - scanline[endX] += subpixelFractionPoint; - scanlineDirty = true; - } - } - - int nextX = startX + 1; - endX = Math.Min(endX, scanline.Length); // reduce to end to the right edge - nextX = Math.Max(nextX, 0); - for (int x = nextX; x < endX; x++) - { - scanline[x] += subpixelFraction; - scanlineDirty = true; - } - } - } - - if (scanlineDirty) - { - if (!options.Antialias) - { - bool hasOnes = false; - bool hasZeros = false; - for (int x = 0; x < scanlineWidth; x++) - { - if (scanline[x] >= 0.5) - { - scanline[x] = 1; - hasOnes = true; - } - else - { - scanline[x] = 0; - hasZeros = true; - } - } - - if (isSolidBrushWithoutBlending && hasOnes != hasZeros) - { - if (hasOnes) - { - source.GetPixelRowSpan(y).Slice(minX, scanlineWidth).Fill(solidBrushColor); - } - - continue; - } - } - - applicator.Apply(scanline, minX, y); - } - } - } - } - } - - private bool IsSolidBrushWithoutBlending(out SolidBrush solidBrush) - { - solidBrush = this.definition.Brush as SolidBrush; - - if (solidBrush == null) - { - return false; - } - - return this.definition.Options.IsOpaqueColorWithoutBlending(solidBrush.Color); - } - } -} diff --git a/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs deleted file mode 100644 index 75774a628..000000000 --- a/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; - -using SixLabors.Fonts; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Primitives; - -namespace SixLabors.ImageSharp.Processing.Processors.Text -{ - /// - /// Defines a processor to draw text on an . - /// - public class DrawTextProcessor : IImageProcessor - { - /// - /// Initializes a new instance of the class. - /// - /// The options - /// The text we want to render - /// The font we want to render with - /// The brush to source pixel colors from. - /// The pen to outline text with. - /// The location on the image to start drawing the text from. - public DrawTextProcessor(TextGraphicsOptions options, string text, Font font, IBrush brush, IPen pen, PointF location) - { - Guard.NotNull(text, nameof(text)); - Guard.NotNull(font, nameof(font)); - - if (brush is null && pen is null) - { - throw new ArgumentNullException($"Expected a {nameof(brush)} or {nameof(pen)}. Both were null"); - } - - this.Options = options; - this.Text = text; - this.Font = font; - this.Location = location; - this.Brush = brush; - this.Pen = pen; - } - - /// - /// Gets the brush used to fill the glyphs. - /// - public IBrush Brush { get; } - - /// - /// Gets the defining blending modes and text-specific drawing settings. - /// - public TextGraphicsOptions Options { get; } - - /// - /// Gets the text to draw. - /// - public string Text { get; } - - /// - /// Gets the pen used for outlining the text, if Null then we will not outline - /// - public IPen Pen { get; } - - /// - /// Gets the font used to render the text. - /// - public Font Font { get; } - - /// - /// Gets the location to draw the text at. - /// - public PointF Location { get; } - - /// - public IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle) - where TPixel : struct, IPixel - => new DrawTextProcessor(configuration, this, source, sourceRectangle); - } -} diff --git a/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor{TPixel}.cs b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor{TPixel}.cs deleted file mode 100644 index c47f764a2..000000000 --- a/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor{TPixel}.cs +++ /dev/null @@ -1,453 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Buffers; -using System.Collections.Generic; - -using SixLabors.Fonts; -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Utils; -using SixLabors.Memory; -using SixLabors.Primitives; -using SixLabors.Shapes; - -namespace SixLabors.ImageSharp.Processing.Processors.Text -{ - /// - /// Using the brush as a source of pixels colors blends the brush color with source. - /// - /// The pixel format. - internal class DrawTextProcessor : ImageProcessor - where TPixel : struct, IPixel - { - private CachingGlyphRenderer textRenderer; - - private readonly DrawTextProcessor definition; - - public DrawTextProcessor(Configuration configuration, DrawTextProcessor definition, Image source, Rectangle sourceRectangle) - : base(configuration, source, sourceRectangle) - { - this.definition = definition; - } - - private TextGraphicsOptions Options => this.definition.Options; - - private Font Font => this.definition.Font; - - private PointF Location => this.definition.Location; - - private string Text => this.definition.Text; - - private IPen Pen => this.definition.Pen; - - private IBrush Brush => this.definition.Brush; - - protected override void BeforeImageApply() - { - base.BeforeImageApply(); - - // do everything at the image level as we are delegating the processing down to other processors - var style = new RendererOptions(this.Font, this.Options.DpiX, this.Options.DpiY, this.Location) - { - ApplyKerning = this.Options.ApplyKerning, - TabWidth = this.Options.TabWidth, - WrappingWidth = this.Options.WrapTextWidth, - HorizontalAlignment = this.Options.HorizontalAlignment, - VerticalAlignment = this.Options.VerticalAlignment - }; - - this.textRenderer = new CachingGlyphRenderer(this.Configuration.MemoryAllocator, this.Text.Length, this.Pen, this.Brush != null); - this.textRenderer.Options = (GraphicsOptions)this.Options; - var renderer = new TextRenderer(this.textRenderer); - renderer.RenderText(this.Text, style); - } - - protected override void AfterImageApply() - { - base.AfterImageApply(); - this.textRenderer?.Dispose(); - this.textRenderer = null; - } - - /// - protected override void OnFrameApply(ImageFrame source) - { - // this is a no-op as we have processes all as an image, we should be able to pass out of before email apply a skip frames outcome - Draw(this.textRenderer.FillOperations, this.Brush); - Draw(this.textRenderer.OutlineOperations, this.Pen?.StrokeFill); - - void Draw(List operations, IBrush brush) - { - if (operations?.Count > 0) - { - using (BrushApplicator app = brush.CreateApplicator(this.Configuration, this.textRenderer.Options, source, this.SourceRectangle)) - { - foreach (DrawingOperation operation in operations) - { - Buffer2D buffer = operation.Map; - int startY = operation.Location.Y; - int startX = operation.Location.X; - int offsetSpan = 0; - if (startX < 0) - { - offsetSpan = -startX; - startX = 0; - } - - if (startX >= source.Width) - { - continue; - } - - int firstRow = 0; - if (startY < 0) - { - firstRow = -startY; - } - - int maxHeight = source.Height - startY; - int end = Math.Min(operation.Map.Height, maxHeight); - - for (int row = firstRow; row < end; row++) - { - int y = startY + row; - Span span = buffer.GetRowSpan(row).Slice(offsetSpan); - app.Apply(span, startX, y); - } - } - } - } - } - } - - private struct DrawingOperation - { - public Buffer2D Map { get; set; } - - public Point Location { get; set; } - } - - private class CachingGlyphRenderer : IGlyphRenderer, IDisposable - { - // just enough accuracy to allow for 1/8 pixel differences which - // later are accumulated while rendering, but do not grow into full pixel offsets - // The value 8 is benchmarked to: - // - Provide a good accuracy (smaller than 0.2% image difference compared to the non-caching variant) - // - Cache hit ratio above 60% - private const float AccuracyMultiple = 8; - - private readonly PathBuilder builder; - - private Point currentRenderPosition; - private (GlyphRendererParameters glyph, PointF subPixelOffset) currentGlyphRenderParams; - private readonly int offset; - private PointF currentPoint; - - private readonly Dictionary<(GlyphRendererParameters glyph, PointF subPixelOffset), GlyphRenderData> - glyphData = new Dictionary<(GlyphRendererParameters glyph, PointF subPixelOffset), GlyphRenderData>(); - - private readonly bool renderOutline; - private readonly bool renderFill; - private bool rasterizationRequired; - - public CachingGlyphRenderer(MemoryAllocator memoryAllocator, int size, IPen pen, bool renderFill) - { - this.MemoryAllocator = memoryAllocator; - this.currentRenderPosition = default; - this.Pen = pen; - this.renderFill = renderFill; - this.renderOutline = pen != null; - this.offset = 2; - if (this.renderFill) - { - this.FillOperations = new List(size); - } - - if (this.renderOutline) - { - this.offset = (int)MathF.Ceiling((pen.StrokeWidth * 2) + 2); - this.OutlineOperations = new List(size); - } - - this.builder = new PathBuilder(); - } - - public List FillOperations { get; } - - public List OutlineOperations { get; } - - public MemoryAllocator MemoryAllocator { get; internal set; } - - public IPen Pen { get; internal set; } - - public GraphicsOptions Options { get; internal set; } - - public void BeginFigure() - { - this.builder.StartFigure(); - } - - public bool BeginGlyph(RectangleF bounds, GlyphRendererParameters parameters) - { - this.currentRenderPosition = Point.Truncate(bounds.Location); - PointF subPixelOffset = bounds.Location - this.currentRenderPosition; - - subPixelOffset.X = MathF.Round(subPixelOffset.X * AccuracyMultiple) / AccuracyMultiple; - subPixelOffset.Y = MathF.Round(subPixelOffset.Y * AccuracyMultiple) / AccuracyMultiple; - - // we have offset our rendering origin a little bit down to prevent edge cropping, move the draw origin up to compensate - this.currentRenderPosition = new Point(this.currentRenderPosition.X - this.offset, this.currentRenderPosition.Y - this.offset); - this.currentGlyphRenderParams = (parameters, subPixelOffset); - - if (this.glyphData.ContainsKey(this.currentGlyphRenderParams)) - { - // we have already drawn the glyph vectors skip trying again - this.rasterizationRequired = false; - return false; - } - - // we check to see if we have a render cache and if we do then we render else - this.builder.Clear(); - - // ensure all glyphs render around [zero, zero] so offset negative root positions so when we draw the glyph we can offset it back - this.builder.SetOrigin(new PointF(-(int)bounds.X + this.offset, -(int)bounds.Y + this.offset)); - - this.rasterizationRequired = true; - return true; - } - - public void BeginText(RectangleF bounds) - { - // not concerned about this one - this.OutlineOperations?.Clear(); - this.FillOperations?.Clear(); - } - - public void CubicBezierTo(PointF secondControlPoint, PointF thirdControlPoint, PointF point) - { - this.builder.AddBezier(this.currentPoint, secondControlPoint, thirdControlPoint, point); - this.currentPoint = point; - } - - public void Dispose() - { - foreach (KeyValuePair<(GlyphRendererParameters glyph, PointF subPixelOffset), GlyphRenderData> kv in this.glyphData) - { - kv.Value.Dispose(); - } - - this.glyphData.Clear(); - } - - public void EndFigure() - { - this.builder.CloseFigure(); - } - - public void EndGlyph() - { - GlyphRenderData renderData = default; - - // has the glyph been rendered already? - if (this.rasterizationRequired) - { - IPath path = this.builder.Build(); - - if (this.renderFill) - { - renderData.FillMap = this.Render(path); - } - - if (this.renderOutline) - { - if (this.Pen.StrokePattern.Length == 0) - { - path = path.GenerateOutline(this.Pen.StrokeWidth); - } - else - { - path = path.GenerateOutline(this.Pen.StrokeWidth, this.Pen.StrokePattern); - } - - renderData.OutlineMap = this.Render(path); - } - - this.glyphData[this.currentGlyphRenderParams] = renderData; - } - else - { - renderData = this.glyphData[this.currentGlyphRenderParams]; - } - - if (this.renderFill) - { - this.FillOperations.Add(new DrawingOperation - { - Location = this.currentRenderPosition, - Map = renderData.FillMap - }); - } - - if (this.renderOutline) - { - this.OutlineOperations.Add(new DrawingOperation - { - Location = this.currentRenderPosition, - Map = renderData.OutlineMap - }); - } - } - - private Buffer2D Render(IPath path) - { - Size size = Rectangle.Ceiling(path.Bounds).Size; - size = new Size(size.Width + (this.offset * 2), size.Height + (this.offset * 2)); - - float subpixelCount = 4; - float offset = 0.5f; - if (this.Options.Antialias) - { - offset = 0f; // we are antialiasing skip offsetting as real antialiasing should take care of offset. - subpixelCount = this.Options.AntialiasSubpixelDepth; - if (subpixelCount < 4) - { - subpixelCount = 4; - } - } - - // take the path inside the path builder, scan thing and generate a Buffer2d representing the glyph and cache it. - Buffer2D fullBuffer = this.MemoryAllocator.Allocate2D(size.Width + 1, size.Height + 1, AllocationOptions.Clean); - - using (IMemoryOwner bufferBacking = this.MemoryAllocator.Allocate(path.MaxIntersections)) - using (IMemoryOwner rowIntersectionBuffer = this.MemoryAllocator.Allocate(size.Width)) - { - float subpixelFraction = 1f / subpixelCount; - float subpixelFractionPoint = subpixelFraction / subpixelCount; - Span intersectionSpan = rowIntersectionBuffer.Memory.Span; - Span buffer = bufferBacking.Memory.Span; - - for (int y = 0; y <= size.Height; y++) - { - Span scanline = fullBuffer.GetRowSpan(y); - bool scanlineDirty = false; - float yPlusOne = y + 1; - - for (float subPixel = y; subPixel < yPlusOne; subPixel += subpixelFraction) - { - var start = new PointF(path.Bounds.Left - 1, subPixel); - var end = new PointF(path.Bounds.Right + 1, subPixel); - int pointsFound = path.FindIntersections(start, end, intersectionSpan); - - if (pointsFound == 0) - { - // nothing on this line skip - continue; - } - - for (int i = 0; i < pointsFound && i < intersectionSpan.Length; i++) - { - buffer[i] = intersectionSpan[i].X; - } - - QuickSort.Sort(buffer.Slice(0, pointsFound)); - - for (int point = 0; point < pointsFound; point += 2) - { - // points will be paired up - float scanStart = buffer[point]; - float scanEnd = buffer[point + 1]; - int startX = (int)MathF.Floor(scanStart + offset); - int endX = (int)MathF.Floor(scanEnd + offset); - - if (startX >= 0 && startX < scanline.Length) - { - for (float x = scanStart; x < startX + 1; x += subpixelFraction) - { - scanline[startX] += subpixelFractionPoint; - scanlineDirty = true; - } - } - - if (endX >= 0 && endX < scanline.Length) - { - for (float x = endX; x < scanEnd; x += subpixelFraction) - { - scanline[endX] += subpixelFractionPoint; - scanlineDirty = true; - } - } - - int nextX = startX + 1; - endX = Math.Min(endX, scanline.Length); // reduce to end to the right edge - nextX = Math.Max(nextX, 0); - for (int x = nextX; x < endX; x++) - { - scanline[x] += subpixelFraction; - scanlineDirty = true; - } - } - } - - if (scanlineDirty) - { - if (!this.Options.Antialias) - { - for (int x = 0; x < size.Width; x++) - { - if (scanline[x] >= 0.5) - { - scanline[x] = 1; - } - else - { - scanline[x] = 0; - } - } - } - } - } - } - - return fullBuffer; - } - - public void EndText() - { - } - - public void LineTo(PointF point) - { - this.builder.AddLine(this.currentPoint, point); - this.currentPoint = point; - } - - public void MoveTo(PointF point) - { - this.builder.StartFigure(); - this.currentPoint = point; - } - - public void QuadraticBezierTo(PointF secondControlPoint, PointF point) - { - this.builder.AddBezier(this.currentPoint, secondControlPoint, point); - this.currentPoint = point; - } - - private struct GlyphRenderData : IDisposable - { - public Buffer2D FillMap; - - public Buffer2D OutlineMap; - - public void Dispose() - { - this.FillMap?.Dispose(); - this.OutlineMap?.Dispose(); - } - } - } - } -} diff --git a/src/ImageSharp.Drawing/Processing/RadialGradientBrush.cs b/src/ImageSharp.Drawing/Processing/RadialGradientBrush.cs deleted file mode 100644 index 2b1b6913f..000000000 --- a/src/ImageSharp.Drawing/Processing/RadialGradientBrush.cs +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Primitives; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// A radial gradient brush, defined by center point and radius. - /// - public sealed class RadialGradientBrush : GradientBrush - { - private readonly PointF center; - - private readonly float radius; - - /// - /// The center of the circular gradient and 0 for the color stops. - /// The radius of the circular gradient and 1 for the color stops. - /// Defines how the colors in the gradient are repeated. - /// the color stops as defined in base class. - public RadialGradientBrush( - PointF center, - float radius, - GradientRepetitionMode repetitionMode, - params ColorStop[] colorStops) - : base(repetitionMode, colorStops) - { - this.center = center; - this.radius = radius; - } - - /// - public override BrushApplicator CreateApplicator( - Configuration configuration, - GraphicsOptions options, - ImageFrame source, - RectangleF region) => - new RadialGradientBrushApplicator( - configuration, - options, - source, - this.center, - this.radius, - this.ColorStops, - this.RepetitionMode); - - /// - private sealed class RadialGradientBrushApplicator : GradientBrushApplicator - where TPixel : struct, IPixel - { - private readonly PointF center; - - private readonly float radius; - - /// - /// Initializes a new instance of the class. - /// - /// The configuration instance to use when performing operations. - /// The graphics options. - /// The target image. - /// Center point of the gradient. - /// Radius of the gradient. - /// Definition of colors. - /// How the colors are repeated beyond the first gradient. - public RadialGradientBrushApplicator( - Configuration configuration, - GraphicsOptions options, - ImageFrame target, - PointF center, - float radius, - ColorStop[] colorStops, - GradientRepetitionMode repetitionMode) - : base(configuration, options, target, colorStops, repetitionMode) - { - this.center = center; - this.radius = radius; - } - - /// - /// As this is a circular gradient, the position on the gradient is based on - /// the distance of the point to the center. - /// - /// The X coordinate of the target pixel. - /// The Y coordinate of the target pixel. - /// the position on the color gradient. - protected override float PositionOnGradient(float x, float y) - { - // TODO: Can this not use Vector2 distance? - float distance = MathF.Sqrt(MathF.Pow(this.center.X - x, 2) + MathF.Pow(this.center.Y - y, 2)); - return distance / this.radius; - } - - internal override void Apply(Span scanline, int x, int y) - { - // TODO: each row is symmetric across center, so we can calculate half of it and mirror it to improve performance. - base.Apply(scanline, x, y); - } - } - } -} diff --git a/src/ImageSharp.Drawing/Processing/RecolorBrush.cs b/src/ImageSharp.Drawing/Processing/RecolorBrush.cs deleted file mode 100644 index e0e43cf78..000000000 --- a/src/ImageSharp.Drawing/Processing/RecolorBrush.cs +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Buffers; -using System.Numerics; -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Memory; -using SixLabors.Primitives; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// Provides an implementation of a brush that can recolor an image - /// - public class RecolorBrush : IBrush - { - /// - /// Initializes a new instance of the class. - /// - /// Color of the source. - /// Color of the target. - /// The threshold as a value between 0 and 1. - public RecolorBrush(Color sourceColor, Color targetColor, float threshold) - { - this.SourceColor = sourceColor; - this.Threshold = threshold; - this.TargetColor = targetColor; - } - - /// - /// Gets the threshold. - /// - public float Threshold { get; } - - /// - /// Gets the source color. - /// - public Color SourceColor { get; } - - /// - /// Gets the target color. - /// - public Color TargetColor { get; } - - /// - public BrushApplicator CreateApplicator( - Configuration configuration, - GraphicsOptions options, - ImageFrame source, - RectangleF region) - where TPixel : struct, IPixel - { - return new RecolorBrushApplicator( - configuration, - options, - source, - this.SourceColor.ToPixel(), - this.TargetColor.ToPixel(), - this.Threshold); - } - - /// - /// The recolor brush applicator. - /// - private class RecolorBrushApplicator : BrushApplicator - where TPixel : struct, IPixel - { - /// - /// The source color. - /// - private readonly Vector4 sourceColor; - - /// - /// The threshold. - /// - private readonly float threshold; - - private readonly TPixel targetColorPixel; - - /// - /// Initializes a new instance of the class. - /// - /// The configuration instance to use when performing operations. - /// The options - /// The source image. - /// Color of the source. - /// Color of the target. - /// The threshold . - public RecolorBrushApplicator( - Configuration configuration, - GraphicsOptions options, - ImageFrame source, - TPixel sourceColor, - TPixel targetColor, - float threshold) - : base(configuration, options, source) - { - this.sourceColor = sourceColor.ToVector4(); - this.targetColorPixel = targetColor; - - // Lets hack a min max extremes for a color space by letting the IPackedPixel clamp our values to something in the correct spaces :) - var maxColor = default(TPixel); - maxColor.FromVector4(new Vector4(float.MaxValue)); - var minColor = default(TPixel); - minColor.FromVector4(new Vector4(float.MinValue)); - this.threshold = Vector4.DistanceSquared(maxColor.ToVector4(), minColor.ToVector4()) * threshold; - } - - /// - internal override TPixel this[int x, int y] - { - get - { - // Offset the requested pixel by the value in the rectangle (the shapes position) - TPixel result = this.Target[x, y]; - var background = result.ToVector4(); - float distance = Vector4.DistanceSquared(background, this.sourceColor); - if (distance <= this.threshold) - { - float lerpAmount = (this.threshold - distance) / this.threshold; - return this.Blender.Blend( - result, - this.targetColorPixel, - lerpAmount); - } - - return result; - } - } - - /// - internal override void Apply(Span scanline, int x, int y) - { - MemoryAllocator memoryAllocator = this.Target.MemoryAllocator; - - using (IMemoryOwner amountBuffer = memoryAllocator.Allocate(scanline.Length)) - using (IMemoryOwner overlay = memoryAllocator.Allocate(scanline.Length)) - { - Span amountSpan = amountBuffer.Memory.Span; - Span overlaySpan = overlay.Memory.Span; - - for (int i = 0; i < scanline.Length; i++) - { - amountSpan[i] = scanline[i] * this.Options.BlendPercentage; - - int offsetX = x + i; - - // No doubt this one can be optimized further but I can't imagine its - // actually being used and can probably be removed/internalized for now - overlaySpan[i] = this[offsetX, y]; - } - - Span destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length); - this.Blender.Blend( - this.Configuration, - destinationRow, - destinationRow, - overlaySpan, - amountSpan); - } - } - } - } -} diff --git a/src/ImageSharp.Drawing/Processing/SolidBrush.cs b/src/ImageSharp.Drawing/Processing/SolidBrush.cs deleted file mode 100644 index c297ede21..000000000 --- a/src/ImageSharp.Drawing/Processing/SolidBrush.cs +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Buffers; - -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Memory; -using SixLabors.Primitives; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// Provides an implementation of a solid brush for painting solid color areas. - /// - public class SolidBrush : IBrush - { - /// - /// Initializes a new instance of the class. - /// - /// The color. - public SolidBrush(Color color) - { - this.Color = color; - } - - /// - /// Gets the color. - /// - public Color Color { get; } - - /// - public BrushApplicator CreateApplicator( - Configuration configuration, - GraphicsOptions options, - ImageFrame source, - RectangleF region) - where TPixel : struct, IPixel - { - return new SolidBrushApplicator(configuration, options, source, this.Color.ToPixel()); - } - - /// - /// The solid brush applicator. - /// - private class SolidBrushApplicator : BrushApplicator - where TPixel : struct, IPixel - { - private bool isDisposed; - - /// - /// Initializes a new instance of the class. - /// - /// The configuration instance to use when performing operations. - /// The graphics options. - /// The source image. - /// The color. - public SolidBrushApplicator( - Configuration configuration, - GraphicsOptions options, - ImageFrame source, - TPixel color) - : base(configuration, options, source) - { - this.Colors = source.MemoryAllocator.Allocate(source.Width); - this.Colors.Memory.Span.Fill(color); - } - - /// - /// Gets the colors. - /// - protected IMemoryOwner Colors { get; private set; } - - /// - internal override TPixel this[int x, int y] => this.Colors.Memory.Span[x]; - - /// - protected override void Dispose(bool disposing) - { - if (this.isDisposed) - { - return; - } - - if (disposing) - { - this.Colors.Dispose(); - } - - this.Colors = null; - this.isDisposed = true; - } - - /// - internal override void Apply(Span scanline, int x, int y) - { - Span destinationRow = this.Target.GetPixelRowSpan(y).Slice(x); - - // constrain the spans to each other - if (destinationRow.Length > scanline.Length) - { - destinationRow = destinationRow.Slice(0, scanline.Length); - } - else - { - scanline = scanline.Slice(0, destinationRow.Length); - } - - MemoryAllocator memoryAllocator = this.Target.MemoryAllocator; - Configuration configuration = this.Configuration; - - if (this.Options.BlendPercentage == 1f) - { - this.Blender.Blend(configuration, destinationRow, destinationRow, this.Colors.Memory.Span, scanline); - } - else - { - using (IMemoryOwner amountBuffer = memoryAllocator.Allocate(scanline.Length)) - { - Span amountSpan = amountBuffer.Memory.Span; - - for (int i = 0; i < scanline.Length; i++) - { - amountSpan[i] = scanline[i] * this.Options.BlendPercentage; - } - - this.Blender.Blend( - configuration, - destinationRow, - destinationRow, - this.Colors.Memory.Span, - amountSpan); - } - } - } - } - } -} diff --git a/src/ImageSharp.Drawing/Processing/TextGraphicsOptions.cs b/src/ImageSharp.Drawing/Processing/TextGraphicsOptions.cs deleted file mode 100644 index 63730d1bf..000000000 --- a/src/ImageSharp.Drawing/Processing/TextGraphicsOptions.cs +++ /dev/null @@ -1,217 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.Fonts; -using SixLabors.ImageSharp.PixelFormats; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// Options for influencing the drawing functions. - /// - public class TextGraphicsOptions : IDeepCloneable - { - private int antialiasSubpixelDepth = 16; - private float blendPercentage = 1F; - private float tabWidth = 4F; - private float dpiX = 72F; - private float dpiY = 72F; - - /// - /// Initializes a new instance of the class. - /// - public TextGraphicsOptions() - { - } - - private TextGraphicsOptions(TextGraphicsOptions source) - { - this.AlphaCompositionMode = source.AlphaCompositionMode; - this.Antialias = source.Antialias; - this.AntialiasSubpixelDepth = source.AntialiasSubpixelDepth; - this.ApplyKerning = source.ApplyKerning; - this.BlendPercentage = source.BlendPercentage; - this.ColorBlendingMode = source.ColorBlendingMode; - this.DpiX = source.DpiX; - this.DpiY = source.DpiY; - this.HorizontalAlignment = source.HorizontalAlignment; - this.TabWidth = source.TabWidth; - this.WrapTextWidth = source.WrapTextWidth; - this.VerticalAlignment = source.VerticalAlignment; - } - - /// - /// Gets or sets a value indicating whether antialiasing should be applied. - /// Defaults to true. - /// - public bool Antialias { get; set; } = true; - - /// - /// Gets or sets a value indicating the number of subpixels to use while rendering with antialiasing enabled. - /// - public int AntialiasSubpixelDepth - { - get - { - return this.antialiasSubpixelDepth; - } - - set - { - Guard.MustBeGreaterThanOrEqualTo(value, 0, nameof(this.AntialiasSubpixelDepth)); - this.antialiasSubpixelDepth = value; - } - } - - /// - /// Gets or sets a value indicating the blending percentage to apply to the drawing operation. - /// - public float BlendPercentage - { - get - { - return this.blendPercentage; - } - - set - { - Guard.MustBeBetweenOrEqualTo(value, 0, 1F, nameof(this.BlendPercentage)); - this.blendPercentage = value; - } - } - - /// - /// Gets or sets a value indicating the color blending percentage to apply to the drawing operation. - /// Defaults to . - /// - public PixelColorBlendingMode ColorBlendingMode { get; set; } = PixelColorBlendingMode.Normal; - - /// - /// Gets or sets a value indicating the color blending percentage to apply to the drawing operation - /// Defaults to . - /// - public PixelAlphaCompositionMode AlphaCompositionMode { get; set; } = PixelAlphaCompositionMode.SrcOver; - - /// - /// Gets or sets a value indicating whether the text should be drawing with kerning enabled. - /// Defaults to true; - /// - public bool ApplyKerning { get; set; } = true; - - /// - /// Gets or sets a value indicating the number of space widths a tab should lock to. - /// Defaults to 4. - /// - public float TabWidth - { - get - { - return this.tabWidth; - } - - set - { - Guard.MustBeGreaterThanOrEqualTo(value, 0, nameof(this.TabWidth)); - this.tabWidth = value; - } - } - - /// - /// Gets or sets a value, if greater than 0, indicating the width at which text should wrap. - /// Defaults to 0. - /// - public float WrapTextWidth { get; set; } - - /// - /// Gets or sets a value indicating the DPI (Dots Per Inch) to render text along the X axis. - /// Defaults to 72. - /// - public float DpiX - { - get - { - return this.dpiX; - } - - set - { - Guard.MustBeGreaterThanOrEqualTo(value, 0, nameof(this.DpiX)); - this.dpiX = value; - } - } - - /// - /// Gets or sets a value indicating the DPI (Dots Per Inch) to render text along the Y axis. - /// Defaults to 72. - /// - public float DpiY - { - get - { - return this.dpiY; - } - - set - { - Guard.MustBeGreaterThanOrEqualTo(value, 0, nameof(this.DpiY)); - this.dpiY = value; - } - } - - /// - /// Gets or sets a value indicating how to align the text relative to the rendering space. - /// If is greater than zero it will align relative to the space - /// defined by the location and width, if equals zero, and thus - /// wrapping disabled, then the alignment is relative to the drawing location. - /// Defaults to . - /// - public HorizontalAlignment HorizontalAlignment { get; set; } = HorizontalAlignment.Left; - - /// - /// Gets or sets a value indicating how to align the text relative to the rendering space. - /// Defaults to . - /// - public VerticalAlignment VerticalAlignment { get; set; } = VerticalAlignment.Top; - - /// - /// Performs an implicit conversion from to . - /// - /// The options. - /// - /// The result of the conversion. - /// - public static implicit operator TextGraphicsOptions(GraphicsOptions options) - { - return new TextGraphicsOptions() - { - Antialias = options.Antialias, - AntialiasSubpixelDepth = options.AntialiasSubpixelDepth, - blendPercentage = options.BlendPercentage, - ColorBlendingMode = options.ColorBlendingMode, - AlphaCompositionMode = options.AlphaCompositionMode - }; - } - - /// - /// Performs an explicit conversion from to . - /// - /// The options. - /// - /// The result of the conversion. - /// - public static explicit operator GraphicsOptions(TextGraphicsOptions options) - { - return new GraphicsOptions() - { - Antialias = options.Antialias, - AntialiasSubpixelDepth = options.AntialiasSubpixelDepth, - ColorBlendingMode = options.ColorBlendingMode, - AlphaCompositionMode = options.AlphaCompositionMode, - BlendPercentage = options.BlendPercentage - }; - } - - /// - public TextGraphicsOptions DeepClone() => new TextGraphicsOptions(this); - } -} diff --git a/src/ImageSharp.Drawing/Utils/NumberUtils.cs b/src/ImageSharp.Drawing/Utils/NumberUtils.cs deleted file mode 100644 index d034c5d7e..000000000 --- a/src/ImageSharp.Drawing/Utils/NumberUtils.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Runtime.CompilerServices; - -namespace SixLabors.ImageSharp -{ - /// - /// Utility methods for numeric primitives. - /// - internal static class NumberUtils - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float ClampFloat(float value, float min, float max) - { - if (value >= max) - { - return max; - } - - if (value <= min) - { - return min; - } - - return value; - } - } -} diff --git a/src/ImageSharp.Drawing/Utils/QuickSort.cs b/src/ImageSharp.Drawing/Utils/QuickSort.cs deleted file mode 100644 index 14e3146a0..000000000 --- a/src/ImageSharp.Drawing/Utils/QuickSort.cs +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Runtime.CompilerServices; - -namespace SixLabors.ImageSharp.Utils -{ - /// - /// Optimized quick sort implementation for Span{float} input - /// - internal class QuickSort - { - /// - /// Sorts the elements of in ascending order - /// - /// The items to sort - public static void Sort(Span data) - { - if (data.Length < 2) - { - return; - } - - if (data.Length == 2) - { - if (data[0] > data[1]) - { - Swap(ref data[0], ref data[1]); - } - - return; - } - - Sort(ref data[0], 0, data.Length - 1); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void Swap(ref float left, ref float right) - { - float tmp = left; - left = right; - right = tmp; - } - - private static void Sort(ref float data0, int lo, int hi) - { - if (lo < hi) - { - int p = Partition(ref data0, lo, hi); - Sort(ref data0, lo, p); - Sort(ref data0, p + 1, hi); - } - } - - private static int Partition(ref float data0, int lo, int hi) - { - float pivot = Unsafe.Add(ref data0, lo); - int i = lo - 1; - int j = hi + 1; - while (true) - { - do - { - i = i + 1; - } - while (Unsafe.Add(ref data0, i) < pivot && i < hi); - - do - { - j = j - 1; - } - while (Unsafe.Add(ref data0, j) > pivot && j > lo); - - if (i >= j) - { - return j; - } - - Swap(ref Unsafe.Add(ref data0, i), ref Unsafe.Add(ref data0, j)); - } - } - } -} diff --git a/src/ImageSharp.Drawing/Processing/Extensions/DrawImageExtensions.cs b/src/ImageSharp/Drawing/Processing/Extensions/DrawImageExtensions.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/Extensions/DrawImageExtensions.cs rename to src/ImageSharp/Drawing/Processing/Extensions/DrawImageExtensions.cs diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs b/src/ImageSharp/Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs rename to src/ImageSharp/Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs b/src/ImageSharp/Drawing/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs rename to src/ImageSharp/Drawing/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawBeziers.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawBeziers.cs deleted file mode 100644 index 8f4a7dfcb..000000000 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawBeziers.cs +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Drawing; -using System.Drawing.Drawing2D; -using System.IO; -using System.Numerics; -using BenchmarkDotNet.Attributes; - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; - -namespace SixLabors.ImageSharp.Benchmarks -{ - public class DrawBeziers : BenchmarkBase - { - [Benchmark(Baseline = true, Description = "System.Drawing Draw Beziers")] - public void DrawPathSystemDrawing() - { - using (var destination = new Bitmap(800, 800)) - using (var graphics = Graphics.FromImage(destination)) - { - graphics.InterpolationMode = InterpolationMode.Default; - graphics.SmoothingMode = SmoothingMode.AntiAlias; - - using (var pen = new System.Drawing.Pen(System.Drawing.Color.HotPink, 10)) - { - graphics.DrawBeziers(pen, new[] { - new PointF(10, 500), - new PointF(30, 10), - new PointF(240, 30), - new PointF(300, 500) - }); - } - - using (var stream = new MemoryStream()) - { - destination.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp); - } - } - } - - [Benchmark(Description = "ImageSharp Draw Beziers")] - public void DrawLinesCore() - { - using (var image = new Image(800, 800)) - { - image.Mutate(x => x.DrawBeziers( - Rgba32.HotPink, - 10, - new Vector2(10, 500), - new Vector2(30, 10), - new Vector2(240, 30), - new Vector2(300, 500))); - - using (var stream = new MemoryStream()) - { - image.SaveAsBmp(stream); - } - } - } - } -} diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawLines.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawLines.cs deleted file mode 100644 index 43b7672c4..000000000 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawLines.cs +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Drawing; -using System.Drawing.Drawing2D; -using System.IO; -using System.Numerics; - -using BenchmarkDotNet.Attributes; - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; - -namespace SixLabors.ImageSharp.Benchmarks -{ - public class DrawLines : BenchmarkBase - { - [Benchmark(Baseline = true, Description = "System.Drawing Draw Lines")] - public void DrawPathSystemDrawing() - { - using (var destination = new Bitmap(800, 800)) - using (var graphics = Graphics.FromImage(destination)) - { - graphics.InterpolationMode = InterpolationMode.Default; - graphics.SmoothingMode = SmoothingMode.AntiAlias; - - using (var pen = new System.Drawing.Pen(System.Drawing.Color.HotPink, 10)) - { - graphics.DrawLines(pen, new[] { - new PointF(10, 10), - new PointF(550, 50), - new PointF(200, 400) - }); - } - - using (var stream = new MemoryStream()) - { - destination.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp); - } - } - } - - [Benchmark(Description = "ImageSharp Draw Lines")] - public void DrawLinesCore() - { - using (var image = new Image(800, 800)) - { - image.Mutate(x => x.DrawLines( - Rgba32.HotPink, - 10, - new Vector2(10, 10), - new Vector2(550, 50), - new Vector2(200, 400))); - - using (var stream = new MemoryStream()) - { - image.SaveAsBmp(stream); - } - } - } - } -} diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawPolygon.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawPolygon.cs deleted file mode 100644 index f20469b63..000000000 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawPolygon.cs +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Drawing; -using System.Drawing.Drawing2D; -using BenchmarkDotNet.Attributes; -using System.IO; -using System.Numerics; - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; - -namespace SixLabors.ImageSharp.Benchmarks -{ - public class DrawPolygon : BenchmarkBase - { - [Benchmark(Baseline = true, Description = "System.Drawing Draw Polygon")] - public void DrawPolygonSystemDrawing() - { - using (var destination = new Bitmap(800, 800)) - using (var graphics = Graphics.FromImage(destination)) - { - graphics.InterpolationMode = InterpolationMode.Default; - graphics.SmoothingMode = SmoothingMode.AntiAlias; - using (var pen = new System.Drawing.Pen(System.Drawing.Color.HotPink, 10)) - { - graphics.DrawPolygon(pen, new[] { - new PointF(10, 10), - new PointF(550, 50), - new PointF(200, 400) - }); - } - - using (var stream = new MemoryStream()) - { - destination.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp); - } - } - } - - [Benchmark(Description = "ImageSharp Draw Polygon")] - public void DrawPolygonCore() - { - using (var image = new Image(800, 800)) - { - image.Mutate(x => x.DrawPolygon( - Rgba32.HotPink, - 10, - new Vector2(10, 10), - new Vector2(550, 50), - new Vector2(200, 400))); - - using (var ms = new MemoryStream()) - { - image.SaveAsBmp(ms); - } - } - } - } -} diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawText.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawText.cs deleted file mode 100644 index c19961390..000000000 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawText.cs +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Drawing; -using System.Drawing.Drawing2D; -using BenchmarkDotNet.Attributes; - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using System.Linq; -using SixLabors.ImageSharp.Processing.Processors.Text; - -namespace SixLabors.ImageSharp.Benchmarks -{ - [MemoryDiagnoser] - public class DrawText : BenchmarkBase - { - [Params(10, 100)] - public int TextIterations { get; set; } - public string TextPhrase { get; set; } = "Hello World"; - public string TextToRender => string.Join(" ", Enumerable.Repeat(this.TextPhrase, this.TextIterations)); - - - [Benchmark(Baseline = true, Description = "System.Drawing Draw Text")] - public void DrawTextSystemDrawing() - { - using (var destination = new Bitmap(800, 800)) - using (var graphics = Graphics.FromImage(destination)) - { - graphics.InterpolationMode = InterpolationMode.Default; - graphics.SmoothingMode = SmoothingMode.AntiAlias; - using (var font = new Font("Arial", 12, GraphicsUnit.Point)) - { - graphics.DrawString(this.TextToRender, font, System.Drawing.Brushes.HotPink, new RectangleF(10, 10, 780, 780)); - } - } - } - - [Benchmark(Description = "ImageSharp Draw Text - Cached Glyphs")] - public void DrawTextCore() - { - using (var image = new Image(800, 800)) - { - var font = SixLabors.Fonts.SystemFonts.CreateFont("Arial", 12); - image.Mutate(x => x.ApplyProcessor(new DrawTextProcessor(new TextGraphicsOptions { Antialias = true, WrapTextWidth = 780 }, this.TextToRender, font, Processing.Brushes.Solid(Rgba32.HotPink), null, new SixLabors.Primitives.PointF(10, 10)))); - } - } - - [Benchmark(Description = "ImageSharp Draw Text - Nieve")] - public void DrawTextCoreOld() - { - using (var image = new Image(800, 800)) - { - var font = SixLabors.Fonts.SystemFonts.CreateFont("Arial", 12); - image.Mutate(x => DrawTextOldVersion(x, new TextGraphicsOptions { Antialias = true, WrapTextWidth = 780 }, this.TextToRender, font, Processing.Brushes.Solid(Rgba32.HotPink), null, new SixLabors.Primitives.PointF(10, 10))); - } - - IImageProcessingContext DrawTextOldVersion( - IImageProcessingContext source, - TextGraphicsOptions options, - string text, - SixLabors.Fonts.Font font, - IBrush brush, - IPen pen, - SixLabors.Primitives.PointF location) - { - float dpiX = 72; - float dpiY = 72; - - var style = new SixLabors.Fonts.RendererOptions(font, dpiX, dpiY, location) - { - ApplyKerning = options.ApplyKerning, - TabWidth = options.TabWidth, - WrappingWidth = options.WrapTextWidth, - HorizontalAlignment = options.HorizontalAlignment, - VerticalAlignment = options.VerticalAlignment - }; - - Shapes.IPathCollection glyphs = Shapes.TextBuilder.GenerateGlyphs(text, style); - - var pathOptions = (GraphicsOptions)options; - if (brush != null) - { - source.Fill(pathOptions, brush, glyphs); - } - - if (pen != null) - { - source.Draw(pathOptions, pen, glyphs); - } - - return source; - } - } - } -} diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawTextOutline.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawTextOutline.cs deleted file mode 100644 index 7d8b77659..000000000 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawTextOutline.cs +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Drawing; -using System.Drawing.Drawing2D; -using BenchmarkDotNet.Attributes; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using System.Linq; -using SixLabors.ImageSharp.Processing.Processors.Text; - -namespace SixLabors.ImageSharp.Benchmarks -{ - [MemoryDiagnoser] - public class DrawTextOutline : BenchmarkBase - { - [Params(10, 100)] - public int TextIterations { get; set; } - public string TextPhrase { get; set; } = "Hello World"; - public string TextToRender => string.Join(" ", Enumerable.Repeat(this.TextPhrase, this.TextIterations)); - - [Benchmark(Baseline = true, Description = "System.Drawing Draw Text Outline")] - public void DrawTextSystemDrawing() - { - using (var destination = new Bitmap(800, 800)) - using (var graphics = Graphics.FromImage(destination)) - { - graphics.InterpolationMode = InterpolationMode.Default; - graphics.SmoothingMode = SmoothingMode.AntiAlias; - using (var pen = new System.Drawing.Pen(System.Drawing.Color.HotPink, 10)) - using (var font = new Font("Arial", 12, GraphicsUnit.Point)) - using (var gp = new GraphicsPath()) - { - gp.AddString(this.TextToRender, font.FontFamily, (int)font.Style, font.Size, new RectangleF(10, 10, 780, 780), new StringFormat()); - graphics.DrawPath(pen, gp); - } - } - } - - [Benchmark(Description = "ImageSharp Draw Text Outline - Cached Glyphs")] - public void DrawTextCore() - { - using (var image = new Image(800, 800)) - { - var font = SixLabors.Fonts.SystemFonts.CreateFont("Arial", 12); - image.Mutate(x => x.ApplyProcessor(new DrawTextProcessor(new TextGraphicsOptions { Antialias = true, WrapTextWidth = 780 }, this.TextToRender, font, null, Processing.Pens.Solid(Rgba32.HotPink, 10), new SixLabors.Primitives.PointF(10, 10)))); - } - } - - [Benchmark(Description = "ImageSharp Draw Text Outline - Nieve")] - public void DrawTextCoreOld() - { - using (var image = new Image(800, 800)) - { - var font = SixLabors.Fonts.SystemFonts.CreateFont("Arial", 12); - image.Mutate( - x => DrawTextOldVersion( - x, - new TextGraphicsOptions { Antialias = true, WrapTextWidth = 780 }, - this.TextToRender, - font, - null, - Processing.Pens.Solid(Rgba32.HotPink, 10), - new SixLabors.Primitives.PointF(10, 10))); - } - - IImageProcessingContext DrawTextOldVersion( - IImageProcessingContext source, - TextGraphicsOptions options, - string text, - SixLabors.Fonts.Font font, - IBrush brush, - IPen pen, - SixLabors.Primitives.PointF location) - { - var style = new SixLabors.Fonts.RendererOptions(font, options.DpiX, options.DpiY, location) - { - ApplyKerning = options.ApplyKerning, - TabWidth = options.TabWidth, - WrappingWidth = options.WrapTextWidth, - HorizontalAlignment = options.HorizontalAlignment, - VerticalAlignment = options.VerticalAlignment - }; - - Shapes.IPathCollection glyphs = Shapes.TextBuilder.GenerateGlyphs(text, style); - - var pathOptions = (GraphicsOptions)options; - if (brush != null) - { - source.Fill(pathOptions, brush, glyphs); - } - - if (pen != null) - { - source.Draw(pathOptions, pen, glyphs); - } - - return source; - } - } - } -} diff --git a/tests/ImageSharp.Benchmarks/Drawing/FillPolygon.cs b/tests/ImageSharp.Benchmarks/Drawing/FillPolygon.cs deleted file mode 100644 index f33df7ec6..000000000 --- a/tests/ImageSharp.Benchmarks/Drawing/FillPolygon.cs +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Drawing; -using System.Drawing.Drawing2D; -using System.IO; -using System.Numerics; -using SixLabors.Shapes; -using BenchmarkDotNet.Attributes; - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; - -namespace SixLabors.ImageSharp.Benchmarks -{ - public class FillPolygon : BenchmarkBase - { - private readonly Polygon shape; - - public FillPolygon() - { - this.shape = new Polygon(new LinearLineSegment( - new Vector2(10, 10), - new Vector2(550, 50), - new Vector2(200, 400))); - } - - [Benchmark(Baseline = true, Description = "System.Drawing Fill Polygon")] - public void DrawSolidPolygonSystemDrawing() - { - using (var destination = new Bitmap(800, 800)) - - using (var graphics = Graphics.FromImage(destination)) - { - graphics.SmoothingMode = SmoothingMode.AntiAlias; - graphics.FillPolygon(System.Drawing.Brushes.HotPink, - new[] { - new Point(10, 10), - new Point(550, 50), - new Point(200, 400) - }); - - using (var stream = new MemoryStream()) - { - destination.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp); - } - } - } - - [Benchmark(Description = "ImageSharp Fill Polygon")] - public void DrawSolidPolygonCore() - { - using (var image = new Image(800, 800)) - { - image.Mutate(x => x.FillPolygon( - Rgba32.HotPink, - new Vector2(10, 10), - new Vector2(550, 50), - new Vector2(200, 400))); - - using (var stream = new MemoryStream()) - { - image.SaveAsBmp(stream); - } - } - } - - [Benchmark(Description = "ImageSharp Fill Polygon - cached shape")] - public void DrawSolidPolygonCoreCached() - { - using (var image = new Image(800, 800)) - { - image.Mutate(x => x.Fill( - Rgba32.HotPink, - this.shape)); - - using (var stream = new MemoryStream()) - { - image.SaveAsBmp(stream); - } - } - } - } -} diff --git a/tests/ImageSharp.Benchmarks/Drawing/FillRectangle.cs b/tests/ImageSharp.Benchmarks/Drawing/FillRectangle.cs deleted file mode 100644 index 531c540da..000000000 --- a/tests/ImageSharp.Benchmarks/Drawing/FillRectangle.cs +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Numerics; -using BenchmarkDotNet.Attributes; - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using CoreRectangle = SixLabors.Primitives.Rectangle; -using CoreSize = SixLabors.Primitives.Size; - -namespace SixLabors.ImageSharp.Benchmarks -{ - public class FillRectangle : BenchmarkBase - { - [Benchmark(Baseline = true, Description = "System.Drawing Fill Rectangle")] - public Size FillRectangleSystemDrawing() - { - using (var destination = new Bitmap(800, 800)) - using (var graphics = Graphics.FromImage(destination)) - { - graphics.InterpolationMode = InterpolationMode.Default; - graphics.SmoothingMode = SmoothingMode.AntiAlias; - graphics.FillRectangle(System.Drawing.Brushes.HotPink, new Rectangle(10, 10, 190, 140)); - - return destination.Size; - } - } - - [Benchmark(Description = "ImageSharp Fill Rectangle")] - public CoreSize FillRectangleCore() - { - using (var image = new Image(800, 800)) - { - image.Mutate(x => x.Fill(Rgba32.HotPink, new CoreRectangle(10, 10, 190, 140))); - - return new CoreSize(image.Width, image.Height); - } - } - - [Benchmark(Description = "ImageSharp Fill Rectangle - As Polygon")] - public CoreSize FillPolygonCore() - { - using (var image = new Image(800, 800)) - { - image.Mutate(x => x.FillPolygon( - Rgba32.HotPink, - new Vector2(10, 10), - new Vector2(200, 10), - new Vector2(200, 150), - new Vector2(10, 150))); - - return new CoreSize(image.Width, image.Height); - } - } - } -} diff --git a/tests/ImageSharp.Benchmarks/Drawing/FillWithPattern.cs b/tests/ImageSharp.Benchmarks/Drawing/FillWithPattern.cs deleted file mode 100644 index 411f8210a..000000000 --- a/tests/ImageSharp.Benchmarks/Drawing/FillWithPattern.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Drawing; -using System.Drawing.Drawing2D; -using System.IO; - -using BenchmarkDotNet.Attributes; - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; - -using CoreBrushes = SixLabors.ImageSharp.Processing.Brushes; - -namespace SixLabors.ImageSharp.Benchmarks -{ - public class FillWithPattern - { - [Benchmark(Baseline = true, Description = "System.Drawing Fill with Pattern")] - public void DrawPatternPolygonSystemDrawing() - { - using (var destination = new Bitmap(800, 800)) - using (var graphics = Graphics.FromImage(destination)) - { - graphics.SmoothingMode = SmoothingMode.AntiAlias; - - using (var brush = new HatchBrush(HatchStyle.BackwardDiagonal, System.Drawing.Color.HotPink)) - { - graphics.FillRectangle(brush, new Rectangle(0, 0, 800, 800)); // can't find a way to flood fill with a brush - } - - using (var stream = new MemoryStream()) - { - destination.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp); - } - } - } - - [Benchmark(Description = "ImageSharp Fill with Pattern")] - public void DrawPatternPolygon3Core() - { - using (var image = new Image(800, 800)) - { - image.Mutate(x => x.Fill(CoreBrushes.BackwardDiagonal(Rgba32.HotPink))); - - using (var stream = new MemoryStream()) - { - image.SaveAsBmp(stream); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj b/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj index cd8497ee4..a714d1f0d 100644 --- a/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj +++ b/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj @@ -26,7 +26,6 @@ - diff --git a/tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj b/tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj index fc94668e1..fc764b53b 100644 --- a/tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj +++ b/tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj @@ -22,7 +22,6 @@ - diff --git a/tests/ImageSharp.Tests/Drawing/DrawBezierTests.cs b/tests/ImageSharp.Tests/Drawing/DrawBezierTests.cs deleted file mode 100644 index de5b2bf47..000000000 --- a/tests/ImageSharp.Tests/Drawing/DrawBezierTests.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Numerics; - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; - -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Drawing -{ - [GroupOutput("Drawing")] - public class DrawBezierTests - { - public static readonly TheoryData DrawPathData = new TheoryData - { - { "White", 255, 1.5f }, - { "Red", 255, 3 }, - { "HotPink", 255, 5 }, - { "HotPink", 150, 5 }, - { "White", 255, 15 }, - }; - - [Theory] - [WithSolidFilledImages(nameof(DrawPathData), 300, 450, "Blue", PixelTypes.Rgba32)] - public void DrawBeziers(TestImageProvider provider, string colorName, byte alpha, float thickness) - where TPixel : struct, IPixel - { - var points = new SixLabors.Primitives.PointF[] - { - new Vector2(10, 400), new Vector2(30, 10), new Vector2(240, 30), new Vector2(300, 400) - }; - Rgba32 rgba = TestUtils.GetColorByName(colorName); - rgba.A = alpha; - Color color = rgba; - - FormattableString testDetails = $"{colorName}_A{alpha}_T{thickness}"; - - provider.RunValidatingProcessorTest( x => x.DrawBeziers(color, 5f, points), - testDetails, - appendSourceFileOrDescription: false, - appendPixelTypeToFileName: false); - } - } -} diff --git a/tests/ImageSharp.Tests/Drawing/DrawComplexPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/DrawComplexPolygonTests.cs deleted file mode 100644 index 76d29dff3..000000000 --- a/tests/ImageSharp.Tests/Drawing/DrawComplexPolygonTests.cs +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Numerics; - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.Shapes; - -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Drawing -{ - [GroupOutput("Drawing")] - public class DrawComplexPolygonTests - { - [Theory] - [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, false, false, false)] - [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, true, false, false)] - [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, false, true, false)] - [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, false, false, true)] - public void DrawComplexPolygon(TestImageProvider provider, bool overlap, bool transparent, bool dashed) - where TPixel :struct, IPixel - { - var simplePath = new Polygon(new LinearLineSegment( - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300))); - - var hole1 = new Polygon(new LinearLineSegment( - new Vector2(37, 85), - overlap ? new Vector2(130, 40) : new Vector2(93, 85), - new Vector2(65, 137))); - IPath clipped = simplePath.Clip(hole1); - - Rgba32 colorRgba = Rgba32.White; - if (transparent) - { - colorRgba.A = 150; - } - - Color color = colorRgba; - - string testDetails = ""; - if (overlap) - { - testDetails += "_Overlap"; - } - - if (transparent) - { - testDetails += "_Transparent"; - } - - if (dashed) - { - testDetails += "_Dashed"; - } - - Pen pen = dashed ? Pens.Dash(color, 5f) : Pens.Solid(color, 5f); - - provider.RunValidatingProcessorTest( - x => x.Draw(pen, clipped), - testDetails, - appendPixelTypeToFileName: false, - appendSourceFileOrDescription: false); - } - } -} diff --git a/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs index 61b45729d..202cd04c9 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; - +using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; @@ -127,7 +127,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing using (Image background = provider.GetImage()) using (var overlay = new Image(50, 50)) { - overlay.Mutate(c => c.Fill(Rgba32.Black)); + overlay.GetPixelSpan().Fill(Rgba32.Black); background.Mutate(c => c.DrawImage(overlay, new Point(x, y), PixelColorBlendingMode.Normal, 1F)); diff --git a/tests/ImageSharp.Tests/Drawing/DrawLinesTests.cs b/tests/ImageSharp.Tests/Drawing/DrawLinesTests.cs deleted file mode 100644 index b45fc620b..000000000 --- a/tests/ImageSharp.Tests/Drawing/DrawLinesTests.cs +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Numerics; - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; - -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Drawing -{ - [GroupOutput("Drawing")] - public class DrawLinesTests - { - [Theory] - [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "White", 1f, 2.5, true)] - [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "White", 0.6f, 10, true)] - [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "White", 1f, 5, false)] - [WithBasicTestPatternImages(250, 350, PixelTypes.Bgr24, "Yellow", 1f, 10, true)] - public void DrawLines_Simple(TestImageProvider provider, string colorName, float alpha, float thickness, bool antialias) - where TPixel : struct, IPixel - { - Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); - Pen pen = new Pen(color, thickness); - - DrawLinesImpl(provider, colorName, alpha, thickness, antialias, pen); - } - - [Theory] - [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "White", 1f, 5, false)] - public void DrawLines_Dash(TestImageProvider provider, string colorName, float alpha, float thickness, bool antialias) - where TPixel : struct, IPixel - { - Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); - Pen pen = Pens.Dash(color, thickness); - - DrawLinesImpl(provider, colorName, alpha, thickness, antialias, pen); - } - - [Theory] - [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "LightGreen", 1f, 5, false)] - public void DrawLines_Dot(TestImageProvider provider, string colorName, float alpha, float thickness, bool antialias) - where TPixel : struct, IPixel - { - Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); - Pen pen = Pens.Dot(color, thickness); - - DrawLinesImpl(provider, colorName, alpha, thickness, antialias, pen); - } - - [Theory] - [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "Yellow", 1f, 5, false)] - public void DrawLines_DashDot(TestImageProvider provider, string colorName, float alpha, float thickness, bool antialias) - where TPixel : struct, IPixel - { - Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); - Pen pen = Pens.DashDot(color, thickness); - - DrawLinesImpl(provider, colorName, alpha, thickness, antialias, pen); - } - - [Theory] - [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "Black", 1f, 5, false)] - public void DrawLines_DashDotDot(TestImageProvider provider, string colorName, float alpha, float thickness, bool antialias) - where TPixel : struct, IPixel - { - Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); - Pen pen = Pens.DashDotDot(color, thickness); - - DrawLinesImpl(provider, colorName, alpha, thickness, antialias, pen); - } - - - private static void DrawLinesImpl( - TestImageProvider provider, - string colorName, - float alpha, - float thickness, - bool antialias, - Pen pen) - where TPixel : struct, IPixel - { - SixLabors.Primitives.PointF[] simplePath = { new Vector2(10, 10), new Vector2(200, 150), new Vector2(50, 300) }; - - GraphicsOptions options = new GraphicsOptions { Antialias = antialias }; - - string aa = antialias ? "" : "_NoAntialias"; - FormattableString outputDetails = $"{colorName}_A({alpha})_T({thickness}){aa}"; - - provider.RunValidatingProcessorTest( - c => c.DrawLines(options, pen, simplePath), - outputDetails, - appendSourceFileOrDescription: false); - } - - } -} diff --git a/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs b/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs deleted file mode 100644 index 8c2c6fc6e..000000000 --- a/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Numerics; - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.Primitives; -using SixLabors.Shapes; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Drawing -{ - [GroupOutput("Drawing")] - public class DrawPathTests - { - public static readonly TheoryData DrawPathData = new TheoryData - { - { "White", 255, 1.5f }, - { "Red", 255, 3 }, - { "HotPink", 255, 5 }, - { "HotPink", 150, 5 }, - { "White", 255, 15 }, - }; - - [Theory] - [WithSolidFilledImages(nameof(DrawPathData), 300, 450, "Blue", PixelTypes.Rgba32)] - public void DrawPath(TestImageProvider provider, string colorName, byte alpha, float thickness) - where TPixel : struct, IPixel - { - var linearSegment = new LinearLineSegment( - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300)); - var bezierSegment = new CubicBezierLineSegment( - new Vector2(50, 300), - new Vector2(500, 500), - new Vector2(60, 10), - new Vector2(10, 400)); - - var path = new Path(linearSegment, bezierSegment); - - Rgba32 rgba = TestUtils.GetColorByName(colorName); - rgba.A = alpha; - Color color = rgba; - - FormattableString testDetails = $"{colorName}_A{alpha}_T{thickness}"; - - provider.RunValidatingProcessorTest( - x => x.Draw(color, thickness, path), - testDetails, - appendPixelTypeToFileName: false, - appendSourceFileOrDescription: false); - } - - [Theory] - [WithSolidFilledImages(256, 256, "Black", PixelTypes.Rgba32)] - public void PathExtendingOffEdgeOfImageShouldNotBeCropped(TestImageProvider provider) - where TPixel : struct, IPixel - { - var color = Color.White; - Pen pen = Pens.Solid(color, 5f); - - provider.RunValidatingProcessorTest( - x => - { - for (int i = 0; i < 300; i += 20) - { - var points = new PointF[] { new Vector2(100, 2), new Vector2(-10, i) }; - x.DrawLines(pen, points); - } - }, - appendPixelTypeToFileName: false, - appendSourceFileOrDescription: false); - } - } -} diff --git a/tests/ImageSharp.Tests/Drawing/DrawPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/DrawPolygonTests.cs deleted file mode 100644 index 4a6cb430a..000000000 --- a/tests/ImageSharp.Tests/Drawing/DrawPolygonTests.cs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Numerics; - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Drawing -{ - [GroupOutput("Drawing")] - public class DrawPolygonTests - { - [Theory] - [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "White", 1f, 2.5, true)] - [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "White", 0.6f, 10, true)] - [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "White", 1f, 5, false)] - [WithBasicTestPatternImages(250, 350, PixelTypes.Bgr24, "Yellow", 1f, 10, true)] - public void DrawPolygon(TestImageProvider provider, string colorName, float alpha, float thickness, bool antialias) - where TPixel : struct, IPixel - { - SixLabors.Primitives.PointF[] simplePath = - { - new Vector2(10, 10), new Vector2(200, 150), new Vector2(50, 300) - }; - Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); - - GraphicsOptions options = new GraphicsOptions { Antialias = antialias }; - - string aa = antialias ? "" : "_NoAntialias"; - FormattableString outputDetails = $"{colorName}_A({alpha})_T({thickness}){aa}"; - - provider.RunValidatingProcessorTest( - c => c.DrawPolygon(options, color, thickness, simplePath), - outputDetails, - appendSourceFileOrDescription: false); - } - } -} diff --git a/tests/ImageSharp.Tests/Drawing/FillComplexPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/FillComplexPolygonTests.cs deleted file mode 100644 index e0fff8da5..000000000 --- a/tests/ImageSharp.Tests/Drawing/FillComplexPolygonTests.cs +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Numerics; - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.Shapes; - -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Drawing -{ - [GroupOutput("Drawing")] - public class FillComplexPolygonTests - { - [Theory] - [WithSolidFilledImages(300, 400, "Blue", PixelTypes.Rgba32, false, false)] - [WithSolidFilledImages(300, 400, "Blue", PixelTypes.Rgba32, true, false)] - [WithSolidFilledImages(300, 400, "Blue", PixelTypes.Rgba32, false, true)] - public void ComplexPolygon_SolidFill(TestImageProvider provider, bool overlap, bool transparent) - where TPixel :struct, IPixel - { - var simplePath = new Polygon(new LinearLineSegment( - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300))); - - var hole1 = new Polygon(new LinearLineSegment( - new Vector2(37, 85), - overlap ? new Vector2(130, 40) : new Vector2(93, 85), - new Vector2(65, 137))); - IPath clipped = simplePath.Clip(hole1); - - Rgba32 colorRgba = Rgba32.HotPink; - if (transparent) - { - colorRgba.A = 150; - } - - Color color = colorRgba; - - string testDetails = ""; - if (overlap) - { - testDetails += "_Overlap"; - } - - if (transparent) - { - testDetails += "_Transparent"; - } - - provider.RunValidatingProcessorTest( - x => x.Fill(color, clipped), - testDetails, - appendPixelTypeToFileName: false, - appendSourceFileOrDescription: false); - } - } -} diff --git a/tests/ImageSharp.Tests/Drawing/FillEllipticGradientBrushTest.cs b/tests/ImageSharp.Tests/Drawing/FillEllipticGradientBrushTest.cs deleted file mode 100644 index c61f770c9..000000000 --- a/tests/ImageSharp.Tests/Drawing/FillEllipticGradientBrushTest.cs +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; - -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Drawing -{ - using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; - - [GroupOutput("Drawing/GradientBrushes")] - public class FillEllipticGradientBrushTests - { - public static ImageComparer TolerantComparer = ImageComparer.TolerantPercentage(0.01f); - - [Theory] - [WithBlankImages(10, 10, PixelTypes.Rgba32)] - public void WithEqualColorsReturnsUnicolorImage( - TestImageProvider provider) - where TPixel : struct, IPixel - { - Color red = Color.Red; - - using (Image image = provider.GetImage()) - { - var unicolorLinearGradientBrush = - new EllipticGradientBrush( - new SixLabors.Primitives.Point(0, 0), - new SixLabors.Primitives.Point(10, 0), - 1.0f, - GradientRepetitionMode.None, - new ColorStop(0, red), - new ColorStop(1, red)); - - image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); - - image.DebugSave(provider, appendPixelTypeToFileName: false, appendSourceFileOrDescription: false); - - // no need for reference image in this test: - image.ComparePixelBufferTo(red); - } - } - - [Theory] - [WithBlankImages(200, 200, PixelTypes.Rgba32, 0.1)] - [WithBlankImages(200, 200, PixelTypes.Rgba32, 0.4)] - [WithBlankImages(200, 200, PixelTypes.Rgba32, 0.8)] - [WithBlankImages(200, 200, PixelTypes.Rgba32, 1.0)] - [WithBlankImages(200, 200, PixelTypes.Rgba32, 1.2)] - [WithBlankImages(200, 200, PixelTypes.Rgba32, 1.6)] - [WithBlankImages(200, 200, PixelTypes.Rgba32, 2.0)] - public void AxisParallelEllipsesWithDifferentRatio( - TestImageProvider provider, - float ratio) - where TPixel : struct, IPixel - { - Color yellow = Color.Yellow; - Color red = Color.Red; - Color black = Color.Black; - - provider.VerifyOperation( - TolerantComparer, - image => - { - var unicolorLinearGradientBrush = new EllipticGradientBrush( - new SixLabors.Primitives.Point(image.Width / 2, image.Height / 2), - new SixLabors.Primitives.Point(image.Width / 2, (image.Width * 2) / 3), - ratio, - GradientRepetitionMode.None, - new ColorStop(0, yellow), - new ColorStop(1, red), - new ColorStop(1, black)); - - image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); - }, - $"{ratio:F2}", - false, - false); - } - - [Theory] - [WithBlankImages(200, 200, PixelTypes.Rgba32, 0.1, 0)] - [WithBlankImages(200, 200, PixelTypes.Rgba32, 0.4, 0)] - [WithBlankImages(200, 200, PixelTypes.Rgba32, 0.8, 0)] - [WithBlankImages(200, 200, PixelTypes.Rgba32, 1.0, 0)] - - [WithBlankImages(200, 200, PixelTypes.Rgba32, 0.1, 45)] - [WithBlankImages(200, 200, PixelTypes.Rgba32, 0.4, 45)] - [WithBlankImages(200, 200, PixelTypes.Rgba32, 0.8, 45)] - [WithBlankImages(200, 200, PixelTypes.Rgba32, 1.0, 45)] - - [WithBlankImages(200, 200, PixelTypes.Rgba32, 0.1, 90)] - [WithBlankImages(200, 200, PixelTypes.Rgba32, 0.4, 90)] - [WithBlankImages(200, 200, PixelTypes.Rgba32, 0.8, 90)] - [WithBlankImages(200, 200, PixelTypes.Rgba32, 1.0, 90)] - - [WithBlankImages(200, 200, PixelTypes.Rgba32, 0.1, 30)] - [WithBlankImages(200, 200, PixelTypes.Rgba32, 0.4, 30)] - [WithBlankImages(200, 200, PixelTypes.Rgba32, 0.8, 30)] - [WithBlankImages(200, 200, PixelTypes.Rgba32, 1.0, 30)] - public void RotatedEllipsesWithDifferentRatio( - TestImageProvider provider, - float ratio, - float rotationInDegree) - where TPixel: struct, IPixel - { - FormattableString variant = $"{ratio:F2}_AT_{rotationInDegree:00}deg"; - - provider.VerifyOperation( - TolerantComparer, - image => - { - Color yellow = Color.Yellow; - Color red = Color.Red; - Color black = Color.Black; - - var center = new SixLabors.Primitives.Point(image.Width / 2, image.Height / 2); - - double rotation = (Math.PI * rotationInDegree) / 180.0; - double cos = Math.Cos(rotation); - double sin = Math.Sin(rotation); - - int offsetY = image.Height / 6; - int axisX = center.X + (int)-(offsetY * sin); - int axisY = center.Y + (int)(offsetY * cos); - - var unicolorLinearGradientBrush = new EllipticGradientBrush( - center, - new SixLabors.Primitives.Point(axisX, axisY), - ratio, - GradientRepetitionMode.None, - new ColorStop(0, yellow), - new ColorStop(1, red), - new ColorStop(1, black)); - - image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); - }, - variant, - false, - false); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Drawing/FillImageBrushTests.cs b/tests/ImageSharp.Tests/Drawing/FillImageBrushTests.cs deleted file mode 100644 index cbf49b830..000000000 --- a/tests/ImageSharp.Tests/Drawing/FillImageBrushTests.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.Primitives; - -using Xunit; - -// ReSharper disable InconsistentNaming - -namespace SixLabors.ImageSharp.Tests.Drawing -{ - [GroupOutput("Drawing")] - public class FillImageBrushTests - { - [Fact] - public void DoesNotDisposeImage() - { - using (var src = new Image(5, 5)) - { - var brush = new ImageBrush(src); - using (var dest = new Image(10, 10)) - { - dest.Mutate(c => c.Fill(brush, new Rectangle(0, 0, 10, 10))); - dest.Mutate(c => c.Fill(brush, new Rectangle(0, 0, 10, 10))); - } - } - } - - [Theory] - [WithTestPatternImages(200, 200, PixelTypes.Rgba32 | PixelTypes.Bgra32)] - public void UseBrushOfDifferentPixelType(TestImageProvider provider) - where TPixel : struct, IPixel - { - byte[] data = TestFile.Create(TestImages.Png.Ducky).Bytes; - using (Image background = provider.GetImage()) - using (Image overlay = provider.PixelType == PixelTypes.Rgba32 - ? (Image)Image.Load(data) - : Image.Load(data)) - { - var brush = new ImageBrush(overlay); - background.Mutate(c => c.Fill(brush)); - - background.DebugSave(provider, appendSourceFileOrDescription : false); - background.CompareToReferenceOutput(provider, appendSourceFileOrDescription: false); - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs b/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs deleted file mode 100644 index 224e07b1e..000000000 --- a/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs +++ /dev/null @@ -1,453 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Globalization; -using System.Linq; -using System.Text; - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; - -using Xunit; -// ReSharper disable InconsistentNaming - -namespace SixLabors.ImageSharp.Tests.Drawing -{ - using SixLabors.ImageSharp.Advanced; - using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; - using SixLabors.Primitives; - using SixLabors.Shapes; - - [GroupOutput("Drawing/GradientBrushes")] - public class FillLinearGradientBrushTests - { - public static ImageComparer TolerantComparer = ImageComparer.TolerantPercentage(0.01f); - - [Theory] - [WithBlankImages(10, 10, PixelTypes.Rgba32)] - public void WithEqualColorsReturnsUnicolorImage(TestImageProvider provider) - where TPixel : struct, IPixel - { - using (Image image = provider.GetImage()) - { - Color red = Color.Red; - - var unicolorLinearGradientBrush = new LinearGradientBrush( - new SixLabors.Primitives.Point(0, 0), - new SixLabors.Primitives.Point(10, 0), - GradientRepetitionMode.None, - new ColorStop(0, red), - new ColorStop(1, red)); - - image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); - - image.DebugSave(provider, appendPixelTypeToFileName: false, appendSourceFileOrDescription: false); - - // no need for reference image in this test: - image.ComparePixelBufferTo(red); - } - } - - [Theory] - [WithBlankImages(20, 10, PixelTypes.Rgba32)] - [WithBlankImages(20, 10, PixelTypes.Argb32)] - [WithBlankImages(20, 10, PixelTypes.Rgb24)] - public void DoesNotDependOnSinglePixelType(TestImageProvider provider) - where TPixel : struct, IPixel - { - provider.VerifyOperation( - TolerantComparer, - image => - { - var unicolorLinearGradientBrush = new LinearGradientBrush( - new SixLabors.Primitives.Point(0, 0), - new SixLabors.Primitives.Point(image.Width, 0), - GradientRepetitionMode.None, - new ColorStop(0, Color.Blue), - new ColorStop(1, Color.Yellow)); - - image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); - }, - appendSourceFileOrDescription: false); - } - - [Theory] - [WithBlankImages(500, 10, PixelTypes.Rgba32)] - public void HorizontalReturnsUnicolorColumns(TestImageProvider provider) - where TPixel : struct, IPixel - { - provider.VerifyOperation( - TolerantComparer, - image => - { - Color red = Color.Red; - Color yellow = Color.Yellow; - - var unicolorLinearGradientBrush = new LinearGradientBrush( - new SixLabors.Primitives.Point(0, 0), - new SixLabors.Primitives.Point(image.Width, 0), - GradientRepetitionMode.None, - new ColorStop(0, red), - new ColorStop(1, yellow)); - - image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); - }, - false, - false); - } - - [Theory] - [WithBlankImages(500, 10, PixelTypes.Rgba32, GradientRepetitionMode.DontFill)] - [WithBlankImages(500, 10, PixelTypes.Rgba32, GradientRepetitionMode.None)] - [WithBlankImages(500, 10, PixelTypes.Rgba32, GradientRepetitionMode.Repeat)] - [WithBlankImages(500, 10, PixelTypes.Rgba32, GradientRepetitionMode.Reflect)] - public void HorizontalGradientWithRepMode( - TestImageProvider provider, - GradientRepetitionMode repetitionMode) - where TPixel : struct, IPixel - { - provider.VerifyOperation( - TolerantComparer, - image => - { - Color red = Color.Red; - Color yellow = Color.Yellow; - - var unicolorLinearGradientBrush = new LinearGradientBrush( - new SixLabors.Primitives.Point(0, 0), - new SixLabors.Primitives.Point(image.Width / 10, 0), - repetitionMode, - new ColorStop(0, red), - new ColorStop(1, yellow)); - - image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); - }, - $"{repetitionMode}", - false, - false); - } - - [Theory] - [WithBlankImages(200, 100, PixelTypes.Rgba32, new[] { 0.5f })] - [WithBlankImages(200, 100, PixelTypes.Rgba32, new[] { 0.2f, 0.4f, 0.6f, 0.8f })] - [WithBlankImages(200, 100, PixelTypes.Rgba32, new[] { 0.1f, 0.3f, 0.6f })] - public void WithDoubledStopsProduceDashedPatterns( - TestImageProvider provider, - float[] pattern) - where TPixel : struct, IPixel - { - string variant = string.Join("_", pattern.Select(i => i.ToString(CultureInfo.InvariantCulture))); - - // ensure the input data is valid - Assert.True(pattern.Length > 0); - - Color black = Color.Black; - Color white = Color.White; - - // create the input pattern: 0, followed by each of the arguments twice, followed by 1.0 - toggling black and white. - ColorStop[] colorStops = - Enumerable.Repeat(new ColorStop(0, black), 1) - .Concat( - pattern - .SelectMany((f, index) => new[] - { - new ColorStop(f, index % 2 == 0 ? black : white), - new ColorStop(f, index % 2 == 0 ? white : black) - })) - .Concat(Enumerable.Repeat(new ColorStop(1, pattern.Length % 2 == 0 ? black : white), 1)) - .ToArray(); - - using (Image image = provider.GetImage()) - { - var unicolorLinearGradientBrush = - new LinearGradientBrush( - new SixLabors.Primitives.Point(0, 0), - new SixLabors.Primitives.Point(image.Width, 0), - GradientRepetitionMode.None, - colorStops); - - image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); - - image.DebugSave( - provider, - variant, - appendPixelTypeToFileName: false, - appendSourceFileOrDescription: false); - - // the result must be a black and white pattern, no other color should occur: - Assert.All( - Enumerable.Range(0, image.Width).Select(i => image[i, 0]), - color => Assert.True( - color.Equals(black.ToPixel()) || color.Equals(white.ToPixel()))); - - image.CompareToReferenceOutput( - TolerantComparer, - provider, - variant, - appendPixelTypeToFileName: false, - appendSourceFileOrDescription: false); - } - } - - [Theory] - [WithBlankImages(10, 500, PixelTypes.Rgba32)] - public void VerticalBrushReturnsUnicolorRows( - TestImageProvider provider) - where TPixel : struct, IPixel - { - provider.VerifyOperation( - image => - { - Color red = Color.Red; - Color yellow = Color.Yellow; - - var unicolorLinearGradientBrush = new LinearGradientBrush( - new SixLabors.Primitives.Point(0, 0), - new SixLabors.Primitives.Point(0, image.Height), - GradientRepetitionMode.None, - new ColorStop(0, red), - new ColorStop(1, yellow)); - - image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); - - VerifyAllRowsAreUnicolor(image); - }, - false, - false); - - void VerifyAllRowsAreUnicolor(Image image) - { - for (int y = 0; y < image.Height; y++) - { - Span row = image.GetPixelRowSpan(y); - TPixel firstColorOfRow = row[0]; - foreach (TPixel p in row) - { - Assert.Equal(firstColorOfRow, p); - } - } - } - } - - public enum ImageCorner - { - TopLeft = 0, - TopRight = 1, - BottomLeft = 2, - BottomRight = 3 - } - - [Theory] - [WithBlankImages(200, 200, PixelTypes.Rgba32, ImageCorner.TopLeft)] - [WithBlankImages(200, 200, PixelTypes.Rgba32, ImageCorner.TopRight)] - [WithBlankImages(200, 200, PixelTypes.Rgba32, ImageCorner.BottomLeft)] - [WithBlankImages(200, 200, PixelTypes.Rgba32, ImageCorner.BottomRight)] - public void DiagonalReturnsCorrectImages( - TestImageProvider provider, - ImageCorner startCorner) - where TPixel : struct, IPixel - { - using (Image image = provider.GetImage()) - { - Assert.True(image.Height == image.Width, "For the math check block at the end the image must be squared, but it is not."); - - int startX = (int)startCorner % 2 == 0 ? 0 : image.Width - 1; - int startY = startCorner > ImageCorner.TopRight ? 0 : image.Height - 1; - int endX = image.Height - startX - 1; - int endY = image.Width - startY - 1; - - Color red = Color.Red; - Color yellow = Color.Yellow; - - var unicolorLinearGradientBrush = - new LinearGradientBrush( - new SixLabors.Primitives.Point(startX, startY), - new SixLabors.Primitives.Point(endX, endY), - GradientRepetitionMode.None, - new ColorStop(0, red), - new ColorStop(1, yellow)); - - image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); - image.DebugSave( - provider, - startCorner, - appendPixelTypeToFileName: false, - appendSourceFileOrDescription: false); - - int verticalSign = startY == 0 ? 1 : -1; - int horizontalSign = startX == 0 ? 1 : -1; - - for (int i = 0; i < image.Height; i++) - { - // it's diagonal, so for any (a, a) on the gradient line, for all (a-x, b+x) - +/- depending on the diagonal direction - must be the same color) - TPixel colorOnDiagonal = image[i, i]; - - // TODO: This is incorrect. from -0 to < 0 ?? - int orthoCount = 0; - for (int offset = -orthoCount; offset < orthoCount; offset++) - { - Assert.Equal(colorOnDiagonal, image[i + (horizontalSign * offset), i + (verticalSign * offset)]); - } - } - - image.CompareToReferenceOutput( - TolerantComparer, - provider, - startCorner, - appendPixelTypeToFileName: false, - appendSourceFileOrDescription: false); - } - } - - [Theory] - [WithBlankImages(500, 500, PixelTypes.Rgba32, 0, 0, 499, 499, new[] { 0f, .2f, .5f, .9f }, new[] { 0, 0, 1, 1 })] - [WithBlankImages(500, 500, PixelTypes.Rgba32, 0, 499, 499, 0, new[] { 0f, 0.2f, 0.5f, 0.9f }, new[] { 0, 1, 2, 3 })] - [WithBlankImages(500, 500, PixelTypes.Rgba32, 499, 499, 0, 0, new[] { 0f, 0.7f, 0.8f, 0.9f }, new[] { 0, 1, 2, 0 })] - [WithBlankImages(500, 500, PixelTypes.Rgba32, 0, 0, 499, 499, new[] { 0f, .5f, 1f }, new[] { 0, 1, 3 })] - public void ArbitraryGradients( - TestImageProvider provider, - int startX, int startY, - int endX, int endY, - float[] stopPositions, - int[] stopColorCodes) - where TPixel : struct, IPixel - { - Color[] colors = - { - Color.Navy, Color.LightGreen, Color.Yellow, - Color.Red - }; - - var coloringVariant = new StringBuilder(); - var colorStops = new ColorStop[stopPositions.Length]; - - for (int i = 0; i < stopPositions.Length; i++) - { - Color color = colors[stopColorCodes[i % colors.Length]]; - float position = stopPositions[i]; - colorStops[i] = new ColorStop(position, color); - Rgba32 rgba = color; - coloringVariant.AppendFormat(CultureInfo.InvariantCulture, "{0}@{1};", rgba.ToHex(), position); - } - - FormattableString variant = $"({startX},{startY})_TO_({endX},{endY})__[{coloringVariant}]"; - - provider.VerifyOperation( - image => - { - var unicolorLinearGradientBrush = new LinearGradientBrush( - new SixLabors.Primitives.Point(startX, startY), - new SixLabors.Primitives.Point(endX, endY), - GradientRepetitionMode.None, - colorStops); - - image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); - }, - variant, - false, - false); - } - - [Theory] - [WithBlankImages(200, 200, PixelTypes.Rgba32, 0, 0, 199, 199, new[] { 0f, .25f, .5f, .75f, 1f }, new[] { 0, 1, 2, 3, 4 })] - public void MultiplePointGradients( - TestImageProvider provider, - int startX, int startY, - int endX, int endY, - float[] stopPositions, - int[] stopColorCodes) - where TPixel : struct, IPixel - { - Color[] colors = - { - Color.Black, Color.Blue, Color.Red, - Color.White, Color.Lime - }; - - var coloringVariant = new StringBuilder(); - var colorStops = new ColorStop[stopPositions.Length]; - - for (int i = 0; i < stopPositions.Length; i++) - { - Color color = colors[stopColorCodes[i % colors.Length]]; - float position = stopPositions[i]; - colorStops[i] = new ColorStop(position, color); - Rgba32 rgba = color; - coloringVariant.AppendFormat(CultureInfo.InvariantCulture, "{0}@{1};", rgba.ToHex(), position); - } - - FormattableString variant = $"({startX},{startY})_TO_({endX},{endY})__[{coloringVariant}]"; - - provider.VerifyOperation( - image => - { - var unicolorLinearGradientBrush = new LinearGradientBrush( - new SixLabors.Primitives.Point(startX, startY), - new SixLabors.Primitives.Point(endX, endY), - GradientRepetitionMode.None, - colorStops); - - image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); - }, - variant, - false, - false); - } - - [Theory] - [WithBlankImages(200, 200, PixelTypes.Rgba32)] - public void GradientsWithTransparencyOnExistingBackground(TestImageProvider provider) - where TPixel : struct, IPixel - { - provider.VerifyOperation( - image => - { - image.Mutate(i => i.Fill(Color.Red)); - image.Mutate(ApplyGloss); - - }); - - void ApplyGloss(IImageProcessingContext ctx) - { - Size size = ctx.GetCurrentSize(); - IPathCollection glossPath = BuildGloss(size.Width, size.Height); - var graphicsOptions = new GraphicsOptions - { - Antialias = true, - ColorBlendingMode = PixelColorBlendingMode.Normal, - AlphaCompositionMode = PixelAlphaCompositionMode.SrcAtop - }; - var linearGradientBrush = new LinearGradientBrush(new Point(0, 0), new Point(0, size.Height / 2), GradientRepetitionMode.Repeat, new ColorStop(0, Color.White.WithAlpha(0.5f)), new ColorStop(1, Color.White.WithAlpha(0.25f))); - ctx.Fill(graphicsOptions, linearGradientBrush, glossPath); - } - - IPathCollection BuildGloss(int imageWidth, int imageHeight) - { - var pathBuilder = new PathBuilder(); - pathBuilder.AddLine(new PointF(0, 0), new PointF(imageWidth, 0)); - pathBuilder.AddLine(new PointF(imageWidth, 0), new PointF(imageWidth, imageHeight * 0.4f)); - pathBuilder.AddBezier(new PointF(imageWidth, imageHeight * 0.4f), new PointF(imageWidth / 2, imageHeight * 0.6f), new PointF(0, imageHeight * 0.4f)); - pathBuilder.CloseFigure(); - return new PathCollection(pathBuilder.Build()); - } - } - - [Theory] - [WithBlankImages(200, 200, PixelTypes.Rgb24)] - public void BrushApplicatorIsThreadSafeIssue1044(TestImageProvider provider) - where TPixel : struct, IPixel - { - provider.VerifyOperation( - TolerantComparer, - img => - { - var brush = new PathGradientBrush( - new[] { new PointF(0, 0), new PointF(200, 0), new PointF(200, 200), new PointF(0, 200), new PointF(0, 0) }, - new[] { Color.Red, Color.Yellow, Color.Green, Color.DarkCyan, Color.Red }); - - img.Mutate(m => m.Fill(brush)); - }, false, false); - } - } -} diff --git a/tests/ImageSharp.Tests/Drawing/FillPathGradientBrushTests.cs b/tests/ImageSharp.Tests/Drawing/FillPathGradientBrushTests.cs deleted file mode 100644 index 1ab747baf..000000000 --- a/tests/ImageSharp.Tests/Drawing/FillPathGradientBrushTests.cs +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; -using SixLabors.Primitives; - -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Drawing -{ - [GroupOutput("Drawing/GradientBrushes")] - public class FillPathGradientBrushTests - { - public static ImageComparer TolerantComparer = ImageComparer.TolerantPercentage(0.01f); - - [Theory] - [WithBlankImages(10, 10, PixelTypes.Rgba32)] - public void FillRectangleWithDifferentColors(TestImageProvider provider) - where TPixel : struct, IPixel - { - provider.VerifyOperation( - TolerantComparer, - image => - { - PointF[] points = { new PointF(0, 0), new PointF(10, 0), new PointF(10, 10), new PointF(0, 10) }; - Color[] colors = { Color.Black, Color.Red, Color.Yellow, Color.Green }; - - var brush = new PathGradientBrush(points, colors); - - image.Mutate(x => x.Fill(brush)); - image.DebugSave(provider, appendPixelTypeToFileName: false, appendSourceFileOrDescription: false); - }); - } - - [Theory] - [WithBlankImages(10, 10, PixelTypes.Rgba32)] - public void FillTriangleWithDifferentColors(TestImageProvider provider) - where TPixel : struct, IPixel - { - provider.VerifyOperation( - TolerantComparer, - image => - { - PointF[] points = { new PointF(5, 0), new PointF(10, 10), new PointF(0, 10) }; - Color[] colors = { Color.Red, Color.Green, Color.Blue }; - - var brush = new PathGradientBrush(points, colors); - - image.Mutate(x => x.Fill(brush)); - image.DebugSave(provider, appendPixelTypeToFileName: false, appendSourceFileOrDescription: false); - }); - } - - [Theory] - [WithBlankImages(10, 10, PixelTypes.Rgba32)] - public void FillRectangleWithSingleColor(TestImageProvider provider) - where TPixel : struct, IPixel - { - using (Image image = provider.GetImage()) - { - PointF[] points = { new PointF(0, 0), new PointF(10, 0), new PointF(10, 10), new PointF(0, 10) }; - Color[] colors = { Color.Red }; - - var brush = new PathGradientBrush(points, colors); - - image.Mutate(x => x.Fill(brush)); - - image.ComparePixelBufferTo(Color.Red); - } - } - - [Theory] - [WithBlankImages(10, 10, PixelTypes.Rgba32)] - public void ShouldRotateTheColorsWhenThereAreMorePoints(TestImageProvider provider) - where TPixel : struct, IPixel - { - provider.VerifyOperation( - TolerantComparer, - image => - { - PointF[] points = { new PointF(0, 0), new PointF(10, 0), new PointF(10, 10), new PointF(0, 10) }; - Color[] colors = { Color.Red, Color.Yellow }; - - var brush = new PathGradientBrush(points, colors); - - image.Mutate(x => x.Fill(brush)); - image.DebugSave(provider, appendPixelTypeToFileName: false, appendSourceFileOrDescription: false); - }); - } - - [Theory] - [WithBlankImages(10, 10, PixelTypes.Rgba32)] - public void FillWithCustomCenterColor(TestImageProvider provider) - where TPixel : struct, IPixel - { - provider.VerifyOperation( - TolerantComparer, - image => - { - PointF[] points = { new PointF(0, 0), new PointF(10, 0), new PointF(10, 10), new PointF(0, 10) }; - Color[] colors = { Color.Black, Color.Red, Color.Yellow, Color.Green }; - - var brush = new PathGradientBrush(points, colors, Color.White); - - image.Mutate(x => x.Fill(brush)); - image.DebugSave(provider, appendPixelTypeToFileName: false, appendSourceFileOrDescription: false); - }); - } - - [Fact] - public void ShouldThrowArgumentNullExceptionWhenLinesAreNull() - { - Color[] colors = { Color.Black, Color.Red, Color.Yellow, Color.Green }; - - PathGradientBrush Create() => new PathGradientBrush(null, colors, Color.White); - - Assert.Throws(Create); - } - - [Fact] - public void ShouldThrowArgumentOutOfRangeExceptionWhenLessThan3PointsAreGiven() - { - PointF[] points = { new PointF(0, 0), new PointF(10, 0) }; - Color[] colors = { Color.Black, Color.Red, Color.Yellow, Color.Green }; - - PathGradientBrush Create() => new PathGradientBrush(points, colors, Color.White); - - Assert.Throws(Create); - } - - [Fact] - public void ShouldThrowArgumentNullExceptionWhenColorsAreNull() - { - PointF[] points = { new PointF(0, 0), new PointF(10, 0), new PointF(10, 10), new PointF(0, 10) }; - - PathGradientBrush Create() => new PathGradientBrush(points, null, Color.White); - - Assert.Throws(Create); - } - - [Fact] - public void ShouldThrowArgumentOutOfRangeExceptionWhenEmptyColorArrayIsGiven() - { - PointF[] points = { new PointF(0, 0), new PointF(10, 0), new PointF(10, 10), new PointF(0, 10) }; - - var colors = new Color[0]; - - PathGradientBrush Create() => new PathGradientBrush(points, colors, Color.White); - - Assert.Throws(Create); - } - } -} diff --git a/tests/ImageSharp.Tests/Drawing/FillPatternBrushTests.cs b/tests/ImageSharp.Tests/Drawing/FillPatternBrushTests.cs deleted file mode 100644 index 647f28510..000000000 --- a/tests/ImageSharp.Tests/Drawing/FillPatternBrushTests.cs +++ /dev/null @@ -1,278 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; - -using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Primitives; -using SixLabors.ImageSharp.Processing; - -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Drawing -{ - public class FillPatternBrushTests - { - private void Test(string name, Rgba32 background, IBrush brush, Rgba32[,] expectedPattern) - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "FillPatternBrushTests"); - using (var image = new Image(20, 20)) - { - image.Mutate(x => x.Fill(background).Fill(brush)); - - image.Save($"{path}/{name}.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - // lets pick random spots to start checking - var r = new Random(); - var expectedPatternFast = new DenseMatrix(expectedPattern); - int xStride = expectedPatternFast.Columns; - int yStride = expectedPatternFast.Rows; - int offsetX = r.Next(image.Width / xStride) * xStride; - int offsetY = r.Next(image.Height / yStride) * yStride; - for (int x = 0; x < xStride; x++) - { - for (int y = 0; y < yStride; y++) - { - int actualX = x + offsetX; - int actualY = y + offsetY; - Rgba32 expected = expectedPatternFast[y, x]; // inverted pattern - Rgba32 actual = sourcePixels[actualX, actualY]; - if (expected != actual) - { - Assert.True(false, $"Expected {expected} but found {actual} at ({actualX},{actualY})"); - } - } - } - - image.Mutate(x => x.Resize(80, 80, KnownResamplers.NearestNeighbor)); - image.Save($"{path}/{name}x4.png"); - } - } - - [Fact] - public void ImageShouldBeFloodFilledWithPercent10() - { - this.Test( - "Percent10", - Rgba32.Blue, - Brushes.Percent10(Rgba32.HotPink, Rgba32.LimeGreen), - new[,] - { - { Rgba32.HotPink, Rgba32.LimeGreen, Rgba32.LimeGreen, Rgba32.LimeGreen }, - { Rgba32.LimeGreen, Rgba32.LimeGreen, Rgba32.LimeGreen, Rgba32.LimeGreen }, - { Rgba32.LimeGreen, Rgba32.LimeGreen, Rgba32.HotPink, Rgba32.LimeGreen }, - { Rgba32.LimeGreen, Rgba32.LimeGreen, Rgba32.LimeGreen, Rgba32.LimeGreen } - }); - } - - [Fact] - public void ImageShouldBeFloodFilledWithPercent10Transparent() - { - this.Test( - "Percent10_Transparent", - Rgba32.Blue, - Brushes.Percent10(Rgba32.HotPink), - new Rgba32[,] - { - { Rgba32.HotPink, Rgba32.Blue, Rgba32.Blue, Rgba32.Blue }, - { Rgba32.Blue, Rgba32.Blue, Rgba32.Blue, Rgba32.Blue }, - { Rgba32.Blue, Rgba32.Blue, Rgba32.HotPink, Rgba32.Blue }, - { Rgba32.Blue, Rgba32.Blue, Rgba32.Blue, Rgba32.Blue } - }); - } - - [Fact] - public void ImageShouldBeFloodFilledWithPercent20() - { - this.Test( - "Percent20", - Rgba32.Blue, - Brushes.Percent20(Rgba32.HotPink, Rgba32.LimeGreen), - new Rgba32[,] - { - { Rgba32.HotPink, Rgba32.LimeGreen, Rgba32.LimeGreen, Rgba32.LimeGreen }, - { Rgba32.LimeGreen, Rgba32.LimeGreen, Rgba32.HotPink, Rgba32.LimeGreen }, - { Rgba32.HotPink, Rgba32.LimeGreen, Rgba32.LimeGreen, Rgba32.LimeGreen }, - { Rgba32.LimeGreen, Rgba32.LimeGreen, Rgba32.HotPink, Rgba32.LimeGreen } - }); - } - - [Fact] - public void ImageShouldBeFloodFilledWithPercent20_transparent() - { - this.Test( - "Percent20_Transparent", - Rgba32.Blue, - Brushes.Percent20(Rgba32.HotPink), - new Rgba32[,] - { - { Rgba32.HotPink, Rgba32.Blue, Rgba32.Blue, Rgba32.Blue }, - { Rgba32.Blue, Rgba32.Blue, Rgba32.HotPink, Rgba32.Blue }, - { Rgba32.HotPink, Rgba32.Blue, Rgba32.Blue, Rgba32.Blue }, - { Rgba32.Blue, Rgba32.Blue, Rgba32.HotPink, Rgba32.Blue } - }); - } - - [Fact] - public void ImageShouldBeFloodFilledWithHorizontal() - { - this.Test( - "Horizontal", - Rgba32.Blue, - Brushes.Horizontal(Rgba32.HotPink, Rgba32.LimeGreen), - new Rgba32[,] - { - { Rgba32.LimeGreen, Rgba32.LimeGreen, Rgba32.LimeGreen, Rgba32.LimeGreen }, - { Rgba32.HotPink, Rgba32.HotPink, Rgba32.HotPink, Rgba32.HotPink }, - { Rgba32.LimeGreen, Rgba32.LimeGreen, Rgba32.LimeGreen, Rgba32.LimeGreen }, - { Rgba32.LimeGreen, Rgba32.LimeGreen, Rgba32.LimeGreen, Rgba32.LimeGreen } - }); - } - - [Fact] - public void ImageShouldBeFloodFilledWithHorizontal_transparent() - { - this.Test( - "Horizontal_Transparent", - Rgba32.Blue, - Brushes.Horizontal(Rgba32.HotPink), - new Rgba32[,] - { - { Rgba32.Blue, Rgba32.Blue, Rgba32.Blue, Rgba32.Blue }, - { Rgba32.HotPink, Rgba32.HotPink, Rgba32.HotPink, Rgba32.HotPink }, - { Rgba32.Blue, Rgba32.Blue, Rgba32.Blue, Rgba32.Blue }, - { Rgba32.Blue, Rgba32.Blue, Rgba32.Blue, Rgba32.Blue } - }); - } - - [Fact] - public void ImageShouldBeFloodFilledWithMin() - { - this.Test( - "Min", - Rgba32.Blue, - Brushes.Min(Rgba32.HotPink, Rgba32.LimeGreen), - new Rgba32[,] - { - { Rgba32.LimeGreen, Rgba32.LimeGreen, Rgba32.LimeGreen, Rgba32.LimeGreen }, - { Rgba32.LimeGreen, Rgba32.LimeGreen, Rgba32.LimeGreen, Rgba32.LimeGreen }, - { Rgba32.LimeGreen, Rgba32.LimeGreen, Rgba32.LimeGreen, Rgba32.LimeGreen }, - { Rgba32.HotPink, Rgba32.HotPink, Rgba32.HotPink, Rgba32.HotPink } - }); - } - - [Fact] - public void ImageShouldBeFloodFilledWithMin_transparent() - { - this.Test( - "Min_Transparent", - Rgba32.Blue, - Brushes.Min(Rgba32.HotPink), - new Rgba32[,] - { - { Rgba32.Blue, Rgba32.Blue, Rgba32.Blue, Rgba32.Blue }, - { Rgba32.Blue, Rgba32.Blue, Rgba32.Blue, Rgba32.Blue }, - { Rgba32.Blue, Rgba32.Blue, Rgba32.Blue, Rgba32.Blue }, - { Rgba32.HotPink, Rgba32.HotPink, Rgba32.HotPink, Rgba32.HotPink }, - }); - } - - [Fact] - public void ImageShouldBeFloodFilledWithVertical() - { - this.Test( - "Vertical", - Rgba32.Blue, - Brushes.Vertical(Rgba32.HotPink, Rgba32.LimeGreen), - new Rgba32[,] - { - { Rgba32.LimeGreen, Rgba32.HotPink, Rgba32.LimeGreen, Rgba32.LimeGreen }, - { Rgba32.LimeGreen, Rgba32.HotPink, Rgba32.LimeGreen, Rgba32.LimeGreen }, - { Rgba32.LimeGreen, Rgba32.HotPink, Rgba32.LimeGreen, Rgba32.LimeGreen }, - { Rgba32.LimeGreen, Rgba32.HotPink, Rgba32.LimeGreen, Rgba32.LimeGreen } - }); - } - - [Fact] - public void ImageShouldBeFloodFilledWithVertical_transparent() - { - this.Test( - "Vertical_Transparent", - Rgba32.Blue, - Brushes.Vertical(Rgba32.HotPink), - new Rgba32[,] - { - { Rgba32.Blue, Rgba32.HotPink, Rgba32.Blue, Rgba32.Blue }, - { Rgba32.Blue, Rgba32.HotPink, Rgba32.Blue, Rgba32.Blue }, - { Rgba32.Blue, Rgba32.HotPink, Rgba32.Blue, Rgba32.Blue }, - { Rgba32.Blue, Rgba32.HotPink, Rgba32.Blue, Rgba32.Blue } - }); - } - - [Fact] - public void ImageShouldBeFloodFilledWithForwardDiagonal() - { - this.Test( - "ForwardDiagonal", - Rgba32.Blue, - Brushes.ForwardDiagonal(Rgba32.HotPink, Rgba32.LimeGreen), - new Rgba32[,] - { - { Rgba32.LimeGreen, Rgba32.LimeGreen, Rgba32.LimeGreen, Rgba32.HotPink }, - { Rgba32.LimeGreen, Rgba32.LimeGreen, Rgba32.HotPink, Rgba32.LimeGreen }, - { Rgba32.LimeGreen, Rgba32.HotPink, Rgba32.LimeGreen, Rgba32.LimeGreen }, - { Rgba32.HotPink, Rgba32.LimeGreen, Rgba32.LimeGreen, Rgba32.LimeGreen } - }); - } - - [Fact] - public void ImageShouldBeFloodFilledWithForwardDiagonal_transparent() - { - this.Test( - "ForwardDiagonal_Transparent", - Rgba32.Blue, - Brushes.ForwardDiagonal(Rgba32.HotPink), - new Rgba32[,] - { - { Rgba32.Blue, Rgba32.Blue, Rgba32.Blue, Rgba32.HotPink }, - { Rgba32.Blue, Rgba32.Blue, Rgba32.HotPink, Rgba32.Blue }, - { Rgba32.Blue, Rgba32.HotPink, Rgba32.Blue, Rgba32.Blue }, - { Rgba32.HotPink, Rgba32.Blue, Rgba32.Blue, Rgba32.Blue } - }); - } - - [Fact] - public void ImageShouldBeFloodFilledWithBackwardDiagonal() - { - this.Test( - "BackwardDiagonal", - Rgba32.Blue, - Brushes.BackwardDiagonal(Rgba32.HotPink, Rgba32.LimeGreen), - new Rgba32[,] - { - { Rgba32.HotPink, Rgba32.LimeGreen, Rgba32.LimeGreen, Rgba32.LimeGreen }, - { Rgba32.LimeGreen, Rgba32.HotPink, Rgba32.LimeGreen, Rgba32.LimeGreen }, - { Rgba32.LimeGreen, Rgba32.LimeGreen, Rgba32.HotPink, Rgba32.LimeGreen }, - { Rgba32.LimeGreen, Rgba32.LimeGreen, Rgba32.LimeGreen, Rgba32.HotPink } - }); - } - - [Fact] - public void ImageShouldBeFloodFilledWithBackwardDiagonal_transparent() - { - this.Test( - "BackwardDiagonal_Transparent", - Rgba32.Blue, - Brushes.BackwardDiagonal(Rgba32.HotPink), - new Rgba32[,] - { - { Rgba32.HotPink, Rgba32.Blue, Rgba32.Blue, Rgba32.Blue }, - { Rgba32.Blue, Rgba32.HotPink, Rgba32.Blue, Rgba32.Blue }, - { Rgba32.Blue, Rgba32.Blue, Rgba32.HotPink, Rgba32.Blue }, - { Rgba32.Blue, Rgba32.Blue, Rgba32.Blue, Rgba32.HotPink } - }); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Drawing/FillPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/FillPolygonTests.cs deleted file mode 100644 index 22294e76d..000000000 --- a/tests/ImageSharp.Tests/Drawing/FillPolygonTests.cs +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Numerics; - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.Shapes; - -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Drawing -{ - [GroupOutput("Drawing")] - public class FillPolygonTests - { - [Theory] - [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "White", 1f, true)] - [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "White", 0.6f, true)] - [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "White", 1f, false)] - [WithBasicTestPatternImages(250, 350, PixelTypes.Bgr24, "Yellow", 1f, true)] - public void FillPolygon_Solid(TestImageProvider provider, string colorName, float alpha, bool antialias) - where TPixel : struct, IPixel - { - SixLabors.Primitives.PointF[] simplePath = - { - new Vector2(10, 10), new Vector2(200, 150), new Vector2(50, 300) - }; - Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); - - var options = new GraphicsOptions { Antialias = antialias }; - - string aa = antialias ? "" : "_NoAntialias"; - FormattableString outputDetails = $"{colorName}_A{alpha}{aa}"; - - provider.RunValidatingProcessorTest( - c => c.FillPolygon(options, color, simplePath), - outputDetails, - appendSourceFileOrDescription: false); - } - - [Theory] - [WithBasicTestPatternImages(200, 200, PixelTypes.Rgba32)] - public void FillPolygon_Concave(TestImageProvider provider) - where TPixel : struct, IPixel - { - var points = new SixLabors.Primitives.PointF[] - { - new Vector2(8, 8), - new Vector2(64, 8), - new Vector2(64, 64), - new Vector2(120, 64), - new Vector2(120, 120), - new Vector2(8, 120) - }; - - var color = Color.LightGreen; - - provider.RunValidatingProcessorTest( - c => c.FillPolygon(color, points), - appendSourceFileOrDescription: false, - appendPixelTypeToFileName: false); - } - - [Theory] - [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32)] - public void FillPolygon_Pattern(TestImageProvider provider) - where TPixel : struct, IPixel - { - SixLabors.Primitives.PointF[] simplePath = - { - new Vector2(10, 10), new Vector2(200, 150), new Vector2(50, 300) - }; - var color = Color.Yellow; - - var brush = Brushes.Horizontal(color); - - provider.RunValidatingProcessorTest( - c => c.FillPolygon(brush, simplePath), - appendSourceFileOrDescription: false); - } - - [Theory] - [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, TestImages.Png.Ducky)] - [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, TestImages.Bmp.Car)] - public void FillPolygon_ImageBrush(TestImageProvider provider, string brushImageName) - where TPixel : struct, IPixel - { - SixLabors.Primitives.PointF[] simplePath = - { - new Vector2(10, 10), new Vector2(200, 50), new Vector2(50, 200) - }; - - using (Image brushImage = Image.Load(TestFile.Create(brushImageName).Bytes)) - { - var brush = new ImageBrush(brushImage); - - provider.RunValidatingProcessorTest( - c => c.FillPolygon(brush, simplePath), - System.IO.Path.GetFileNameWithoutExtension(brushImageName), - appendSourceFileOrDescription: false); - } - } - - [Theory] - [WithBasicTestPatternImages(250, 250, PixelTypes.Rgba32)] - public void Fill_RectangularPolygon(TestImageProvider provider) - where TPixel : struct, IPixel - { - var polygon = new SixLabors.Shapes.RectangularPolygon(10, 10, 190, 140); - var color = Color.White; - - provider.RunValidatingProcessorTest( - c => c.Fill(color, polygon), - appendSourceFileOrDescription: false); - } - - [Theory] - [WithBasicTestPatternImages(200, 200, PixelTypes.Rgba32, 3, 50, 0f)] - [WithBasicTestPatternImages(200, 200, PixelTypes.Rgba32, 3, 60, 20f)] - [WithBasicTestPatternImages(200, 200, PixelTypes.Rgba32, 3, 60, -180f)] - [WithBasicTestPatternImages(200, 200, PixelTypes.Rgba32, 5, 70, 0f)] - [WithBasicTestPatternImages(200, 200, PixelTypes.Rgba32, 7, 80, -180f)] - public void Fill_RegularPolygon(TestImageProvider provider, int vertices, float radius, float angleDeg) - where TPixel : struct, IPixel - { - float angle = GeometryUtilities.DegreeToRadian(angleDeg); - var polygon = new RegularPolygon(100, 100, vertices, radius, angle); - var color = Color.Yellow; - - FormattableString testOutput = $"V({vertices})_R({radius})_Ang({angleDeg})"; - provider.RunValidatingProcessorTest( - c => c.Fill(color, polygon), - testOutput, - appendSourceFileOrDescription: false, - appendPixelTypeToFileName: false); - } - - [Theory] - [WithBasicTestPatternImages(200, 200, PixelTypes.Rgba32)] - public void Fill_EllipsePolygon(TestImageProvider provider) - where TPixel : struct, IPixel - { - var polygon = new EllipsePolygon(100, 100, 80, 120); - var color = Color.Azure; - - provider.RunValidatingProcessorTest( - c => c.Fill(color, polygon), - appendSourceFileOrDescription: false, - appendPixelTypeToFileName: false); - } - } -} diff --git a/tests/ImageSharp.Tests/Drawing/FillRadialGradientBrushTests.cs b/tests/ImageSharp.Tests/Drawing/FillRadialGradientBrushTests.cs deleted file mode 100644 index 818340dd2..000000000 --- a/tests/ImageSharp.Tests/Drawing/FillRadialGradientBrushTests.cs +++ /dev/null @@ -1,73 +0,0 @@ -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; - -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Drawing -{ - - using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; - - [GroupOutput("Drawing/GradientBrushes")] - public class FillRadialGradientBrushTests - { - public static ImageComparer TolerantComparer = ImageComparer.TolerantPercentage(0.01f); - - [Theory] - [WithBlankImages(200, 200, PixelTypes.Rgba32)] - public void WithEqualColorsReturnsUnicolorImage( - TestImageProvider provider) - where TPixel : struct, IPixel - { - using (Image image = provider.GetImage()) - { - Color red = Color.Red; - - var unicolorRadialGradientBrush = - new RadialGradientBrush( - new SixLabors.Primitives.Point(0, 0), - 100, - GradientRepetitionMode.None, - new ColorStop(0, red), - new ColorStop(1, red)); - - image.Mutate(x => x.Fill(unicolorRadialGradientBrush)); - - image.DebugSave(provider, appendPixelTypeToFileName: false, appendSourceFileOrDescription: false); - - // no need for reference image in this test: - image.ComparePixelBufferTo(red); - } - } - - [Theory] - [WithBlankImages(200, 200, PixelTypes.Rgba32, 100, 100)] - [WithBlankImages(200, 200, PixelTypes.Rgba32, 0, 0)] - [WithBlankImages(200, 200, PixelTypes.Rgba32, 100, 0)] - [WithBlankImages(200, 200, PixelTypes.Rgba32, 0, 100)] - [WithBlankImages(200, 200, PixelTypes.Rgba32, -40, 100)] - public void WithDifferentCentersReturnsImage( - TestImageProvider provider, - int centerX, - int centerY) - where TPixel : struct, IPixel - { - provider.VerifyOperation( - TolerantComparer, - image => - { - var brush = new RadialGradientBrush( - new SixLabors.Primitives.Point(centerX, centerY), - image.Width / 2f, - GradientRepetitionMode.None, - new ColorStop(0, Color.Red), - new ColorStop(1, Color.Yellow)); - - image.Mutate(x => x.Fill(brush)); - }, - $"center({centerX},{centerY})", - false, - false); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs b/tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs deleted file mode 100644 index dd6b07f9a..000000000 --- a/tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Numerics; - -using Moq; -using System; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Primitives; -using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Processing.Processors; -using SixLabors.Primitives; -using Xunit; -using SixLabors.ImageSharp.Processing.Processors.Drawing; -using SixLabors.Shapes; -using SixLabors.ImageSharp.Advanced; - -namespace SixLabors.ImageSharp.Tests.Drawing -{ - public class FillRegionProcessorTests - { - - [Theory] - [InlineData(true, 1, 4)] - [InlineData(true, 2, 4)] - [InlineData(true, 5, 5)] - [InlineData(true, 8, 8)] - [InlineData(false, 8, 4)] - [InlineData(false, 16, 4)] // we always do 4 sub=pixels when antialiasing is off. - public void MinimumAntialiasSubpixelDepth(bool antialias, int antialiasSubpixelDepth, int expectedAntialiasSubpixelDepth) - { - var bounds = new Rectangle(0, 0, 1, 1); - - var brush = new Mock(); - var region = new MockRegion2(bounds); - - var options = new GraphicsOptions - { - Antialias = antialias, - AntialiasSubpixelDepth = 1 - }; - var processor = new FillRegionProcessor(options, brush.Object, region); - var img = new Image(1, 1); - processor.Execute(img.GetConfiguration(), img, bounds); - - Assert.Equal(4, region.ScanInvocationCounter); - } - - [Fact] - public void FillOffCanvas() - { - var bounds = new Rectangle(-100, -10, 10, 10); - var brush = new Mock(); - var options = new GraphicsOptions { Antialias = true }; - var processor = new FillRegionProcessor(options, brush.Object, new MockRegion1()); - var img = new Image(10, 10); - processor.Execute(img.GetConfiguration(), img, bounds); - } - - [Fact] - public void DrawOffCanvas() - { - - using (var img = new Image(10, 10)) - { - img.Mutate(x => x.DrawLines(new Pen(Rgba32.Black, 10), - new Vector2(-10, 5), - new Vector2(20, 5))); - } - } - - [Fact] - public void DoesNotThrowForIssue928() - { - var rectText = new RectangleF(0, 0, 2000, 2000); - using (var img = new Image((int)rectText.Width, (int)rectText.Height)) - { - img.Mutate(x => x.Fill(Rgba32.Transparent)); - - img.Mutate(ctx => - { - ctx.DrawLines( - Rgba32.Red, - 0.984252f, - new PointF(104.762581f, 1074.99365f), - new PointF(104.758667f, 1075.01721f), - new PointF(104.757675f, 1075.04114f), - new PointF(104.759628f, 1075.065f), - new PointF(104.764488f, 1075.08838f), - new PointF(104.772186f, 1075.111f), - new PointF(104.782608f, 1075.13245f), - new PointF(104.782608f, 1075.13245f) - ); - } - ); - } - } - - [Fact] - public void DoesNotThrowFillingTriangle() - { - using (var image = new Image(28, 28)) - { - var path = new Polygon( - new LinearLineSegment(new PointF(17.11f, 13.99659f), new PointF(14.01433f, 27.06201f)), - new LinearLineSegment(new PointF(14.01433f, 27.06201f), new PointF(13.79267f, 14.00023f)), - new LinearLineSegment(new PointF(13.79267f, 14.00023f), new PointF(17.11f, 13.99659f)) - ); - - image.Mutate(ctx => - { - ctx.Fill(Rgba32.White, path); - }); - } - } - - // Mocking the region throws an error in netcore2.0 - private class MockRegion1 : Region - { - public override Rectangle Bounds => new Rectangle(-100, -10, 10, 10); - - public override int Scan(float y, Span buffer, Configuration configuration) - { - if (y < 5) - { - buffer[0] = -10f; - buffer[1] = 100f; - return 2; - } - return 0; - } - - public override int MaxIntersections => 10; - } - - private class MockRegion2 : Region - { - public MockRegion2(Rectangle bounds) - { - this.Bounds = bounds; - } - - public override int MaxIntersections => 100; - - public override Rectangle Bounds { get; } - - public int ScanInvocationCounter { get; private set; } - - public override int Scan(float y, Span buffer, Configuration configuration) - { - this.ScanInvocationCounter++; - return 0; - } - } - } -} diff --git a/tests/ImageSharp.Tests/Drawing/FillSolidBrushTests.cs b/tests/ImageSharp.Tests/Drawing/FillSolidBrushTests.cs deleted file mode 100644 index 1e3688fea..000000000 --- a/tests/ImageSharp.Tests/Drawing/FillSolidBrushTests.cs +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Primitives; -using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; -using SixLabors.Primitives; -using SixLabors.Shapes; - -using Xunit; - -// ReSharper disable InconsistentNaming - -namespace SixLabors.ImageSharp.Tests.Drawing -{ - [GroupOutput("Drawing")] - public class FillSolidBrushTests - { - [Theory] - [WithBlankImages(1, 1, PixelTypes.Rgba32)] - [WithBlankImages(7, 4, PixelTypes.Rgba32)] - [WithBlankImages(16, 7, PixelTypes.Rgba32)] - [WithBlankImages(33, 32, PixelTypes.Rgba32)] - [WithBlankImages(400, 500, PixelTypes.Rgba32)] - public void DoesNotDependOnSize(TestImageProvider provider) - where TPixel : struct, IPixel - { - using (Image image = provider.GetImage()) - { - var color = Color.HotPink; - image.Mutate(c => c.Fill(color)); - - image.DebugSave(provider, appendPixelTypeToFileName: false); - image.ComparePixelBufferTo(color); - } - } - - [Theory] - [WithBlankImages(16, 16, PixelTypes.Rgba32 | PixelTypes.Argb32 | PixelTypes.RgbaVector)] - public void DoesNotDependOnSinglePixelType(TestImageProvider provider) - where TPixel : struct, IPixel - { - using (Image image = provider.GetImage()) - { - var color = Color.HotPink; - image.Mutate(c => c.Fill(color)); - - image.DebugSave(provider, appendSourceFileOrDescription: false); - image.ComparePixelBufferTo(color); - } - } - - [Theory] - [WithSolidFilledImages(16, 16, "Red", PixelTypes.Rgba32, "Blue")] - [WithSolidFilledImages(16, 16, "Yellow", PixelTypes.Rgba32, "Khaki")] - public void WhenColorIsOpaque_OverridePreviousColor( - TestImageProvider provider, - string newColorName) - where TPixel : struct, IPixel - { - using (Image image = provider.GetImage()) - { - Color color = TestUtils.GetColorByName(newColorName); - image.Mutate(c => c.Fill(color)); - - image.DebugSave( - provider, - newColorName, - appendPixelTypeToFileName: false, - appendSourceFileOrDescription: false); - image.ComparePixelBufferTo(color); - } - } - - [Theory] - [WithSolidFilledImages(16, 16, "Red", PixelTypes.Rgba32, 5, 7, 3, 8)] - [WithSolidFilledImages(16, 16, "Red", PixelTypes.Rgba32, 8, 5, 6, 4)] - public void FillRegion(TestImageProvider provider, int x0, int y0, int w, int h) - where TPixel : struct, IPixel - { - FormattableString testDetails = $"(x{x0},y{y0},w{w},h{h})"; - var region = new RectangleF(x0, y0, w, h); - Color color = TestUtils.GetColorByName("Blue"); - - provider.RunValidatingProcessorTest(c => c.Fill(color, region), testDetails, ImageComparer.Exact); - } - - [Theory] - [WithSolidFilledImages(16, 16, "Red", PixelTypes.Rgba32, 5, 7, 3, 8)] - [WithSolidFilledImages(16, 16, "Red", PixelTypes.Rgba32, 8, 5, 6, 4)] - public void FillRegion_WorksOnWrappedMemoryImage( - TestImageProvider provider, - int x0, - int y0, - int w, - int h) - where TPixel : struct, IPixel - { - FormattableString testDetails = $"(x{x0},y{y0},w{w},h{h})"; - var region = new RectangleF(x0, y0, w, h); - Color color = TestUtils.GetColorByName("Blue"); - - provider.RunValidatingProcessorTestOnWrappedMemoryImage( - c => c.Fill(color, region), - testDetails, - ImageComparer.Exact, - useReferenceOutputFrom: nameof(this.FillRegion)); - } - - public static readonly TheoryData BlendData = - new TheoryData - { - { false, "Blue", 0.5f, PixelColorBlendingMode.Normal, 1.0f }, - { false, "Blue", 1.0f, PixelColorBlendingMode.Normal, 0.5f }, - { false, "Green", 0.5f, PixelColorBlendingMode.Normal, 0.3f }, - { false, "HotPink", 0.8f, PixelColorBlendingMode.Normal, 0.8f }, - { false, "Blue", 0.5f, PixelColorBlendingMode.Multiply, 1.0f }, - { false, "Blue", 1.0f, PixelColorBlendingMode.Multiply, 0.5f }, - { false, "Green", 0.5f, PixelColorBlendingMode.Multiply, 0.3f }, - { false, "HotPink", 0.8f, PixelColorBlendingMode.Multiply, 0.8f }, - { false, "Blue", 0.5f, PixelColorBlendingMode.Add, 1.0f }, - { false, "Blue", 1.0f, PixelColorBlendingMode.Add, 0.5f }, - { false, "Green", 0.5f, PixelColorBlendingMode.Add, 0.3f }, - { false, "HotPink", 0.8f, PixelColorBlendingMode.Add, 0.8f }, - { true, "Blue", 0.5f, PixelColorBlendingMode.Normal, 1.0f }, - { true, "Blue", 1.0f, PixelColorBlendingMode.Normal, 0.5f }, - { true, "Green", 0.5f, PixelColorBlendingMode.Normal, 0.3f }, - { true, "HotPink", 0.8f, PixelColorBlendingMode.Normal, 0.8f }, - { true, "Blue", 0.5f, PixelColorBlendingMode.Multiply, 1.0f }, - { true, "Blue", 1.0f, PixelColorBlendingMode.Multiply, 0.5f }, - { true, "Green", 0.5f, PixelColorBlendingMode.Multiply, 0.3f }, - { true, "HotPink", 0.8f, PixelColorBlendingMode.Multiply, 0.8f }, - { true, "Blue", 0.5f, PixelColorBlendingMode.Add, 1.0f }, - { true, "Blue", 1.0f, PixelColorBlendingMode.Add, 0.5f }, - { true, "Green", 0.5f, PixelColorBlendingMode.Add, 0.3f }, - { true, "HotPink", 0.8f, PixelColorBlendingMode.Add, 0.8f }, - }; - - [Theory] - [WithSolidFilledImages(nameof(BlendData), 16, 16, "Red", PixelTypes.Rgba32)] - public void BlendFillColorOverBackground( - TestImageProvider provider, - bool triggerFillRegion, - string newColorName, - float alpha, - PixelColorBlendingMode blenderMode, - float blendPercentage) - where TPixel : struct, IPixel - { - Color fillColor = TestUtils.GetColorByName(newColorName).WithAlpha(alpha); - - using (Image image = provider.GetImage()) - { - TPixel bgColor = image[0, 0]; - - var options = new GraphicsOptions - { - Antialias = false, - ColorBlendingMode = blenderMode, - BlendPercentage = blendPercentage - }; - - if (triggerFillRegion) - { - var region = new ShapeRegion(new RectangularPolygon(0, 0, 16, 16)); - - image.Mutate(c => c.Fill(options, new SolidBrush(fillColor), region)); - } - else - { - image.Mutate(c => c.Fill(options, new SolidBrush(fillColor))); - } - - var testOutputDetails = new - { - triggerFillRegion = triggerFillRegion, - newColorName = newColorName, - alpha = alpha, - blenderMode = blenderMode, - blendPercentage = blendPercentage - }; - - image.DebugSave( - provider, - testOutputDetails, - appendPixelTypeToFileName: false, - appendSourceFileOrDescription: false); - - PixelBlender blender = PixelOperations.Instance.GetPixelBlender( - blenderMode, - PixelAlphaCompositionMode.SrcOver); - TPixel expectedPixel = blender.Blend(bgColor, fillColor.ToPixel(), blendPercentage); - - image.ComparePixelBufferTo(expectedPixel); - } - } - } -} diff --git a/tests/ImageSharp.Tests/Drawing/Paths/DrawPathCollection.cs b/tests/ImageSharp.Tests/Drawing/Paths/DrawPathCollection.cs deleted file mode 100644 index 36c11035c..000000000 --- a/tests/ImageSharp.Tests/Drawing/Paths/DrawPathCollection.cs +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Numerics; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Primitives; -using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Processing.Processors.Drawing; -using SixLabors.ImageSharp.Tests.Processing; -using SixLabors.ImageSharp.Tests.TestUtilities; -using SixLabors.Shapes; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Drawing.Paths -{ - public class DrawPathCollection : BaseImageOperationsExtensionTest - { - private static readonly GraphicsOptionsComparer graphicsOptionsComparer = new GraphicsOptionsComparer(); - - GraphicsOptions nonDefault = new GraphicsOptions { Antialias = false }; - Color color = Color.HotPink; - Pen pen = Pens.Solid(Rgba32.HotPink, 1); - IPath path1 = new Path(new LinearLineSegment(new SixLabors.Primitives.PointF[] { - new Vector2(10,10), - new Vector2(20,10), - new Vector2(20,10), - new Vector2(30,10), - })); - IPath path2 = new Path(new LinearLineSegment(new SixLabors.Primitives.PointF[] { - new Vector2(10,10), - new Vector2(20,10), - new Vector2(20,10), - new Vector2(30,10), - })); - - IPathCollection pathCollection; - - public DrawPathCollection() - { - this.pathCollection = new PathCollection(this.path1, this.path2); - } - - [Fact] - public void CorrectlySetsBrushAndPath() - { - this.operations.Draw(this.pen, this.pathCollection); - - for (int i = 0; i < 2; i++) - { - FillRegionProcessor processor = this.Verify(i); - - Assert.Equal(new GraphicsOptions(), processor.Options, graphicsOptionsComparer); - - ShapePath region = Assert.IsType(processor.Region); - - // path is converted to a polygon before filling - Assert.IsType(region.Shape); - - Assert.Equal(this.pen.StrokeFill, processor.Brush); - } - } - - [Fact] - public void CorrectlySetsBrushPathOptions() - { - this.operations.Draw(this.nonDefault, this.pen, this.pathCollection); - - for (int i = 0; i < 2; i++) - { - FillRegionProcessor processor = this.Verify(i); - - Assert.Equal(this.nonDefault, processor.Options, graphicsOptionsComparer); - - ShapePath region = Assert.IsType(processor.Region); - Assert.IsType(region.Shape); - - Assert.Equal(this.pen.StrokeFill, processor.Brush); - } - } - - [Fact] - public void CorrectlySetsColorAndPath() - { - this.operations.Draw(this.color, 1, this.pathCollection); - - for (int i = 0; i < 2; i++) - { - FillRegionProcessor processor = this.Verify(i); - - Assert.Equal(new GraphicsOptions(), processor.Options, graphicsOptionsComparer); - - ShapePath region = Assert.IsType(processor.Region); - Assert.IsType(region.Shape); - - SolidBrush brush = Assert.IsType(processor.Brush); - Assert.Equal(this.color, brush.Color); - } - } - - [Fact] - public void CorrectlySetsColorPathAndOptions() - { - this.operations.Draw(this.nonDefault, this.color, 1, this.pathCollection); - - for (int i = 0; i < 2; i++) - { - FillRegionProcessor processor = this.Verify(i); - - Assert.Equal(this.nonDefault, processor.Options, graphicsOptionsComparer); - - ShapePath region = Assert.IsType(processor.Region); - Assert.IsType(region.Shape); - - SolidBrush brush = Assert.IsType(processor.Brush); - Assert.Equal(this.color, brush.Color); - } - } - } -} diff --git a/tests/ImageSharp.Tests/Drawing/Paths/FillPath.cs b/tests/ImageSharp.Tests/Drawing/Paths/FillPath.cs deleted file mode 100644 index cea59e15e..000000000 --- a/tests/ImageSharp.Tests/Drawing/Paths/FillPath.cs +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Numerics; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Primitives; -using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Processing.Processors.Drawing; -using SixLabors.ImageSharp.Tests.Processing; -using SixLabors.ImageSharp.Tests.TestUtilities; -using SixLabors.Shapes; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Drawing.Paths -{ - public class FillPath : BaseImageOperationsExtensionTest - { - private static readonly GraphicsOptionsComparer graphicsOptionsComparer = new GraphicsOptionsComparer(); - - GraphicsOptions nonDefault = new GraphicsOptions { Antialias = false }; - Color color = Color.HotPink; - SolidBrush brush = Brushes.Solid(Rgba32.HotPink); - IPath path = new Path(new LinearLineSegment(new SixLabors.Primitives.PointF[] { - new Vector2(10,10), - new Vector2(20,10), - new Vector2(20,10), - new Vector2(30,10), - })); - - [Fact] - public void CorrectlySetsBrushAndPath() - { - this.operations.Fill(this.brush, this.path); - var processor = this.Verify(); - - Assert.Equal(new GraphicsOptions(), processor.Options, graphicsOptionsComparer); - - ShapeRegion region = Assert.IsType(processor.Region); - - // path is converted to a polygon before filling - Polygon polygon = Assert.IsType(region.Shape); - Assert.IsType(polygon.LineSegments[0]); - - Assert.Equal(this.brush, processor.Brush); - } - - [Fact] - public void CorrectlySetsBrushPathOptions() - { - this.operations.Fill(this.nonDefault, this.brush, this.path); - var processor = this.Verify(); - - Assert.Equal(this.nonDefault, processor.Options, graphicsOptionsComparer); - - ShapeRegion region = Assert.IsType(processor.Region); - Polygon polygon = Assert.IsType(region.Shape); - Assert.IsType(polygon.LineSegments[0]); - - Assert.Equal(this.brush, processor.Brush); - } - - [Fact] - public void CorrectlySetsColorAndPath() - { - this.operations.Fill(this.color, this.path); - var processor = this.Verify(); - - Assert.Equal(new GraphicsOptions(), processor.Options, graphicsOptionsComparer); - - ShapeRegion region = Assert.IsType(processor.Region); - Polygon polygon = Assert.IsType(region.Shape); - Assert.IsType(polygon.LineSegments[0]); - - SolidBrush brush = Assert.IsType(processor.Brush); - Assert.Equal(this.color, brush.Color); - } - - [Fact] - public void CorrectlySetsColorPathAndOptions() - { - this.operations.Fill(this.nonDefault, this.color, this.path); - var processor = this.Verify(); - - Assert.Equal(this.nonDefault, processor.Options); - - ShapeRegion region = Assert.IsType(processor.Region); - Polygon polygon = Assert.IsType(region.Shape); - Assert.IsType(polygon.LineSegments[0]); - - SolidBrush brush = Assert.IsType(processor.Brush); - Assert.Equal(this.color, brush.Color); - } - } -} diff --git a/tests/ImageSharp.Tests/Drawing/Paths/FillPathCollection.cs b/tests/ImageSharp.Tests/Drawing/Paths/FillPathCollection.cs deleted file mode 100644 index 2a9c04a89..000000000 --- a/tests/ImageSharp.Tests/Drawing/Paths/FillPathCollection.cs +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Numerics; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Primitives; -using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Processing.Processors.Drawing; -using SixLabors.ImageSharp.Tests.Processing; -using SixLabors.ImageSharp.Tests.TestUtilities; -using SixLabors.Shapes; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Drawing.Paths -{ - public class FillPathCollection : BaseImageOperationsExtensionTest - { - private static readonly GraphicsOptionsComparer graphicsOptionsComparer = new GraphicsOptionsComparer(); - - GraphicsOptions nonDefault = new GraphicsOptions { Antialias = false }; - Color color = Color.HotPink; - SolidBrush brush = Brushes.Solid(Rgba32.HotPink); - IPath path1 = new Path(new LinearLineSegment(new SixLabors.Primitives.PointF[] { - new Vector2(10,10), - new Vector2(20,10), - new Vector2(20,10), - new Vector2(30,10), - })); - IPath path2 = new Path(new LinearLineSegment(new SixLabors.Primitives.PointF[] { - new Vector2(10,10), - new Vector2(20,10), - new Vector2(20,10), - new Vector2(30,10), - })); - - IPathCollection pathCollection; - - public FillPathCollection() - { - this.pathCollection = new PathCollection(this.path1, this.path2); - } - - [Fact] - public void CorrectlySetsBrushAndPath() - { - this.operations.Fill(this.brush, this.pathCollection); - - for (int i = 0; i < 2; i++) - { - FillRegionProcessor processor = this.Verify(i); - - Assert.Equal(new GraphicsOptions(), processor.Options, graphicsOptionsComparer); - - ShapeRegion region = Assert.IsType(processor.Region); - - // path is converted to a polygon before filling - Polygon polygon = Assert.IsType(region.Shape); - Assert.IsType(polygon.LineSegments[0]); - - Assert.Equal(this.brush, processor.Brush); - } - } - - [Fact] - public void CorrectlySetsBrushPathOptions() - { - this.operations.Fill(this.nonDefault, this.brush, this.pathCollection); - - for (int i = 0; i < 2; i++) - { - FillRegionProcessor processor = this.Verify(i); - - Assert.Equal(this.nonDefault, processor.Options, graphicsOptionsComparer); - - ShapeRegion region = Assert.IsType(processor.Region); - Polygon polygon = Assert.IsType(region.Shape); - Assert.IsType(polygon.LineSegments[0]); - - Assert.Equal(this.brush, processor.Brush); - } - } - - [Fact] - public void CorrectlySetsColorAndPath() - { - this.operations.Fill(this.color, this.pathCollection); - - for (int i = 0; i < 2; i++) - { - FillRegionProcessor processor = this.Verify(i); - - Assert.Equal(new GraphicsOptions(), processor.Options, graphicsOptionsComparer); - - ShapeRegion region = Assert.IsType(processor.Region); - Polygon polygon = Assert.IsType(region.Shape); - Assert.IsType(polygon.LineSegments[0]); - - SolidBrush brush = Assert.IsType(processor.Brush); - Assert.Equal(this.color, brush.Color); - } - } - - [Fact] - public void CorrectlySetsColorPathAndOptions() - { - this.operations.Fill(this.nonDefault, this.color, this.pathCollection); - - for (int i = 0; i < 2; i++) - { - FillRegionProcessor processor = this.Verify(i); - - Assert.Equal(this.nonDefault, processor.Options, graphicsOptionsComparer); - - ShapeRegion region = Assert.IsType(processor.Region); - Polygon polygon = Assert.IsType(region.Shape); - Assert.IsType(polygon.LineSegments[0]); - - SolidBrush brush = Assert.IsType(processor.Brush); - Assert.Equal(this.color, brush.Color); - } - } - } -} diff --git a/tests/ImageSharp.Tests/Drawing/Paths/FillPolygon.cs b/tests/ImageSharp.Tests/Drawing/Paths/FillPolygon.cs deleted file mode 100644 index 8dacd1e7f..000000000 --- a/tests/ImageSharp.Tests/Drawing/Paths/FillPolygon.cs +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Numerics; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Primitives; -using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Processing.Processors.Drawing; -using SixLabors.ImageSharp.Tests.Processing; -using SixLabors.ImageSharp.Tests.TestUtilities; -using SixLabors.Shapes; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Drawing.Paths -{ - public class FillPolygon : BaseImageOperationsExtensionTest - { - private static readonly GraphicsOptionsComparer graphicsOptionsComparer = new GraphicsOptionsComparer(); - - GraphicsOptions nonDefault = new GraphicsOptions { Antialias = false }; - Color color = Color.HotPink; - SolidBrush brush = Brushes.Solid(Rgba32.HotPink); - SixLabors.Primitives.PointF[] path = { - new Vector2(10,10), - new Vector2(20,10), - new Vector2(20,10), - new Vector2(30,10), - }; - - - [Fact] - public void CorrectlySetsBrushAndPath() - { - this.operations.FillPolygon(this.brush, this.path); - - FillRegionProcessor processor = this.Verify(); - - Assert.Equal(new GraphicsOptions(), processor.Options, graphicsOptionsComparer); - - ShapeRegion region = Assert.IsType(processor.Region); - Polygon polygon = Assert.IsType(region.Shape); - Assert.IsType(polygon.LineSegments[0]); - - Assert.Equal(this.brush, processor.Brush); - } - - [Fact] - public void CorrectlySetsBrushPathAndOptions() - { - this.operations.FillPolygon(this.nonDefault, this.brush, this.path); - FillRegionProcessor processor = this.Verify(); - - Assert.Equal(this.nonDefault, processor.Options, graphicsOptionsComparer); - - ShapeRegion region = Assert.IsType(processor.Region); - Polygon polygon = Assert.IsType(region.Shape); - Assert.IsType(polygon.LineSegments[0]); - - Assert.Equal(this.brush, processor.Brush); - } - - [Fact] - public void CorrectlySetsColorAndPath() - { - this.operations.FillPolygon(this.color, this.path); - FillRegionProcessor processor = this.Verify(); - - - Assert.Equal(new GraphicsOptions(), processor.Options, graphicsOptionsComparer); - - ShapeRegion region = Assert.IsType(processor.Region); - Polygon polygon = Assert.IsType(region.Shape); - Assert.IsType(polygon.LineSegments[0]); - - SolidBrush brush = Assert.IsType(processor.Brush); - Assert.Equal(this.color, brush.Color); - } - - [Fact] - public void CorrectlySetsColorPathAndOptions() - { - this.operations.FillPolygon(this.nonDefault, this.color, this.path); - FillRegionProcessor processor = this.Verify(); - - Assert.Equal(this.nonDefault, processor.Options, graphicsOptionsComparer); - - ShapeRegion region = Assert.IsType(processor.Region); - Polygon polygon = Assert.IsType(region.Shape); - Assert.IsType(polygon.LineSegments[0]); - - SolidBrush brush = Assert.IsType(processor.Brush); - Assert.Equal(this.color, brush.Color); - } - } -} diff --git a/tests/ImageSharp.Tests/Drawing/Paths/FillRectangle.cs b/tests/ImageSharp.Tests/Drawing/Paths/FillRectangle.cs deleted file mode 100644 index 6b08323b6..000000000 --- a/tests/ImageSharp.Tests/Drawing/Paths/FillRectangle.cs +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Primitives; -using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Processing.Processors.Drawing; -using SixLabors.ImageSharp.Tests.Processing; -using SixLabors.ImageSharp.Tests.TestUtilities; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Drawing.Paths -{ - public class FillRectangle : BaseImageOperationsExtensionTest - { - private static readonly GraphicsOptionsComparer graphicsOptionsComparer = new GraphicsOptionsComparer(); - - private GraphicsOptions nonDefault = new GraphicsOptions { Antialias = false }; - private Color color = Color.HotPink; - private SolidBrush brush = Brushes.Solid(Rgba32.HotPink); - private SixLabors.Primitives.Rectangle rectangle = new SixLabors.Primitives.Rectangle(10, 10, 77, 76); - - [Fact] - public void CorrectlySetsBrushAndRectangle() - { - this.operations.Fill(this.brush, this.rectangle); - FillRegionProcessor processor = this.Verify(); - - Assert.Equal(new GraphicsOptions(), processor.Options, graphicsOptionsComparer); - - ShapeRegion region = Assert.IsType(processor.Region); - Shapes.RectangularPolygon rect = Assert.IsType(region.Shape); - Assert.Equal(rect.Location.X, this.rectangle.X); - Assert.Equal(rect.Location.Y, this.rectangle.Y); - Assert.Equal(rect.Size.Width, this.rectangle.Width); - Assert.Equal(rect.Size.Height, this.rectangle.Height); - - Assert.Equal(this.brush, processor.Brush); - } - - [Fact] - public void CorrectlySetsBrushRectangleAndOptions() - { - this.operations.Fill(this.nonDefault, this.brush, this.rectangle); - FillRegionProcessor processor = this.Verify(); - - Assert.Equal(this.nonDefault, processor.Options, graphicsOptionsComparer); - - ShapeRegion region = Assert.IsType(processor.Region); - Shapes.RectangularPolygon rect = Assert.IsType(region.Shape); - Assert.Equal(rect.Location.X, this.rectangle.X); - Assert.Equal(rect.Location.Y, this.rectangle.Y); - Assert.Equal(rect.Size.Width, this.rectangle.Width); - Assert.Equal(rect.Size.Height, this.rectangle.Height); - - Assert.Equal(this.brush, processor.Brush); - } - - [Fact] - public void CorrectlySetsColorAndRectangle() - { - this.operations.Fill(this.color, this.rectangle); - FillRegionProcessor processor = this.Verify(); - - Assert.Equal(new GraphicsOptions(), processor.Options, graphicsOptionsComparer); - - ShapeRegion region = Assert.IsType(processor.Region); - Shapes.RectangularPolygon rect = Assert.IsType(region.Shape); - Assert.Equal(rect.Location.X, this.rectangle.X); - Assert.Equal(rect.Location.Y, this.rectangle.Y); - Assert.Equal(rect.Size.Width, this.rectangle.Width); - Assert.Equal(rect.Size.Height, this.rectangle.Height); - - SolidBrush brush = Assert.IsType(processor.Brush); - Assert.Equal(this.color, brush.Color); - } - - [Fact] - public void CorrectlySetsColorRectangleAndOptions() - { - this.operations.Fill(this.nonDefault, this.color, this.rectangle); - FillRegionProcessor processor = this.Verify(); - - Assert.Equal(this.nonDefault, processor.Options, graphicsOptionsComparer); - - ShapeRegion region = Assert.IsType(processor.Region); - Shapes.RectangularPolygon rect = Assert.IsType(region.Shape); - Assert.Equal(rect.Location.X, this.rectangle.X); - Assert.Equal(rect.Location.Y, this.rectangle.Y); - Assert.Equal(rect.Size.Width, this.rectangle.Width); - Assert.Equal(rect.Size.Height, this.rectangle.Height); - - SolidBrush brush = Assert.IsType(processor.Brush); - Assert.Equal(this.color, brush.Color); - } - } -} diff --git a/tests/ImageSharp.Tests/Drawing/Paths/ShapePathTests.cs b/tests/ImageSharp.Tests/Drawing/Paths/ShapePathTests.cs deleted file mode 100644 index b474f6e47..000000000 --- a/tests/ImageSharp.Tests/Drawing/Paths/ShapePathTests.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -namespace SixLabors.ImageSharp.Tests.Drawing.Paths -{ - public class ShapePathTests - { - // TODO read these back in - } -} diff --git a/tests/ImageSharp.Tests/Drawing/Paths/ShapeRegionTests.cs b/tests/ImageSharp.Tests/Drawing/Paths/ShapeRegionTests.cs deleted file mode 100644 index 69dff7236..000000000 --- a/tests/ImageSharp.Tests/Drawing/Paths/ShapeRegionTests.cs +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.Primitives; -using System; -using System.Collections.Generic; -using System.Numerics; -using Moq; -using SixLabors.Primitives; -using SixLabors.Shapes; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Drawing.Paths -{ - public class ShapeRegionTests - { - public abstract class MockPath : IPath - { - public abstract RectangleF Bounds { get; } - public IPath AsClosedPath() => this; - - public abstract SegmentInfo PointAlongPath(float distanceAlongPath); - public abstract PointInfo Distance(PointF point); - public abstract IEnumerable Flatten(); - public abstract bool Contains(PointF point); - public abstract IPath Transform(Matrix3x2 matrix); - public abstract PathTypes PathType { get; } - public abstract int MaxIntersections { get; } - public abstract float Length { get; } - - public int FindIntersections(PointF start, PointF end, PointF[] buffer, int offset) - { - return this.FindIntersections(start, end, buffer, 0); - } - - public int FindIntersections(PointF s, PointF e, Span buffer) - { - Assert.Equal(this.TestYToScan, s.Y); - Assert.Equal(this.TestYToScan, e.Y); - Assert.True(s.X < this.Bounds.Left); - Assert.True(e.X > this.Bounds.Right); - - this.TestFindIntersectionsInvocationCounter++; - - return this.TestFindIntersectionsResult; - } - - public int TestFindIntersectionsInvocationCounter { get; private set; } - public virtual int TestYToScan => 10; - public virtual int TestFindIntersectionsResult => 3; - } - - private readonly Mock pathMock; - - private readonly RectangleF bounds; - - public ShapeRegionTests() - { - this.pathMock = new Mock { CallBase = true }; - - this.bounds = new RectangleF(10.5f, 10, 10, 10); - this.pathMock.Setup(x => x.Bounds).Returns(this.bounds); - } - - [Fact] - public void ShapeRegionWithPathRetainsShape() - { - var region = new ShapeRegion(this.pathMock.Object); - - Assert.Equal(this.pathMock.Object, region.Shape); - } - - [Fact] - public void ShapeRegionFromPathConvertsBoundsProxyToShape() - { - var region = new ShapeRegion(this.pathMock.Object); - - Assert.Equal(Math.Floor(this.bounds.Left), region.Bounds.Left); - Assert.Equal(Math.Ceiling(this.bounds.Right), region.Bounds.Right); - - this.pathMock.Verify(x => x.Bounds); - } - - [Fact] - public void ShapeRegionFromPathMaxIntersectionsProxyToShape() - { - var region = new ShapeRegion(this.pathMock.Object); - - int i = region.MaxIntersections; - this.pathMock.Verify(x => x.MaxIntersections); - } - - [Fact] - public void ShapeRegionFromPathScanYProxyToShape() - { - MockPath path = this.pathMock.Object; - int yToScan = path.TestYToScan; - var region = new ShapeRegion(path); - - int i = region.Scan(yToScan, new float[path.TestFindIntersectionsResult], Configuration.Default); - - Assert.Equal(path.TestFindIntersectionsResult, i); - Assert.Equal(1, path.TestFindIntersectionsInvocationCounter); - } - - - [Fact] - public void ShapeRegionFromShapeConvertsBoundsProxyToShape() - { - var region = new ShapeRegion(this.pathMock.Object); - - Assert.Equal(Math.Floor(this.bounds.Left), region.Bounds.Left); - Assert.Equal(Math.Ceiling(this.bounds.Right), region.Bounds.Right); - - this.pathMock.Verify(x => x.Bounds); - } - - [Fact] - public void ShapeRegionFromShapeMaxIntersectionsProxyToShape() - { - var region = new ShapeRegion(this.pathMock.Object); - - int i = region.MaxIntersections; - this.pathMock.Verify(x => x.MaxIntersections); - } - } -} diff --git a/tests/ImageSharp.Tests/Drawing/RecolorImageTests.cs b/tests/ImageSharp.Tests/Drawing/RecolorImageTests.cs deleted file mode 100644 index fae0bf72b..000000000 --- a/tests/ImageSharp.Tests/Drawing/RecolorImageTests.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.Primitives; - -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Drawing -{ - [GroupOutput("Drawing")] - public class RecolorImageTests - { - [Theory] - [WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Rgba32, "Yellow", "Pink", 0.2f)] - [WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Bgra32, "Yellow", "Pink", 0.5f)] - [WithTestPatternImages(100, 100, PixelTypes.Rgba32, "Red", "Blue", 0.2f)] - [WithTestPatternImages(100, 100, PixelTypes.Rgba32, "Red", "Blue", 0.6f)] - public void Recolor(TestImageProvider provider, string sourceColorName, string targetColorName, float threshold) - where TPixel : struct, IPixel - { - Color sourceColor = TestUtils.GetColorByName(sourceColorName); - Color targetColor = TestUtils.GetColorByName(targetColorName); - var brush = new RecolorBrush(sourceColor, targetColor, threshold); - - FormattableString testInfo = $"{sourceColorName}-{targetColorName}-{threshold}"; - provider.RunValidatingProcessorTest(x => x.Fill(brush), testInfo); - } - - [Theory] - [WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Bgra32, "Yellow", "Pink", 0.5f)] - [WithTestPatternImages(100, 100, PixelTypes.Rgba32, "Red", "Blue", 0.2f)] - public void Recolor_InBox(TestImageProvider provider, string sourceColorName, string targetColorName, float threshold) - where TPixel : struct, IPixel - { - Color sourceColor = TestUtils.GetColorByName(sourceColorName); - Color targetColor = TestUtils.GetColorByName(targetColorName); - var brush = new RecolorBrush(sourceColor, targetColor, threshold); - - FormattableString testInfo = $"{sourceColorName}-{targetColorName}-{threshold}"; - provider.RunValidatingProcessorTest(x => - { - Size size = x.GetCurrentSize(); - var rectangle = new Rectangle(0, size.Height / 2 - size.Height / 4, size.Width, size.Height / 2); - x.Fill(brush, rectangle); - }, testInfo); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Drawing/SolidBezierTests.cs b/tests/ImageSharp.Tests/Drawing/SolidBezierTests.cs deleted file mode 100644 index fd8713ccc..000000000 --- a/tests/ImageSharp.Tests/Drawing/SolidBezierTests.cs +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Numerics; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.Shapes; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Drawing -{ - [GroupOutput("Drawing")] - public class SolidBezierTests - { - [Theory] - [WithBlankImages(500, 500, PixelTypes.Rgba32)] - public void FilledBezier(TestImageProvider provider) - where TPixel : struct, IPixel - { - SixLabors.Primitives.PointF[] simplePath = { - new Vector2(10, 400), - new Vector2(30, 10), - new Vector2(240, 30), - new Vector2(300, 400) - }; - - Color blue = Color.Blue; - Color hotPink = Color.HotPink; - - using (Image image = provider.GetImage()) - { - image.Mutate(x => x.BackgroundColor(blue)); - image.Mutate(x => x.Fill(hotPink, new Polygon(new CubicBezierLineSegment(simplePath)))); - image.DebugSave(provider); - image.CompareToReferenceOutput(provider); - } - } - - - [Theory] - [WithBlankImages(500, 500, PixelTypes.Rgba32)] - public void OverlayByFilledPolygonOpacity(TestImageProvider provider) - where TPixel : struct, IPixel - { - SixLabors.Primitives.PointF[] simplePath = { - new Vector2(10, 400), - new Vector2(30, 10), - new Vector2(240, 30), - new Vector2(300, 400) - }; - - var color = new Rgba32(Rgba32.HotPink.R, Rgba32.HotPink.G, Rgba32.HotPink.B, 150); - - using (var image = provider.GetImage() as Image) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - - image.Mutate(x => x.Fill(color, new Polygon(new CubicBezierLineSegment(simplePath)))); - image.DebugSave(provider); - image.CompareToReferenceOutput(provider); - } - } - } -} diff --git a/tests/ImageSharp.Tests/Drawing/SolidFillBlendedShapesTests.cs b/tests/ImageSharp.Tests/Drawing/SolidFillBlendedShapesTests.cs deleted file mode 100644 index f1a62cf29..000000000 --- a/tests/ImageSharp.Tests/Drawing/SolidFillBlendedShapesTests.cs +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. -using System; -using System.Collections.Generic; - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; -using SixLabors.Primitives; -using Xunit; - -// ReSharper disable InconsistentNaming -namespace SixLabors.ImageSharp.Tests.Drawing -{ - [GroupOutput("Drawing")] - public class SolidFillBlendedShapesTests - { - public static IEnumerable modes = GetAllModeCombinations(); - - private static IEnumerable GetAllModeCombinations() - { - foreach (var composition in Enum.GetValues(typeof(PixelAlphaCompositionMode))) - { - foreach (var blending in Enum.GetValues(typeof(PixelColorBlendingMode))) - { - yield return new object[] { blending, composition }; - } - } - } - - - [Theory] - [WithBlankImages(nameof(modes), 250, 250, PixelTypes.Rgba32)] - public void _1DarkBlueRect_2BlendHotPinkRect( - TestImageProvider provider, - PixelColorBlendingMode blending, - PixelAlphaCompositionMode composition) - where TPixel : struct, IPixel - { - using (Image img = provider.GetImage()) - { - int scaleX = img.Width / 100; - int scaleY = img.Height / 100; - img.Mutate( - x => x.Fill( - Color.DarkBlue, - new Rectangle(0 * scaleX, 40 * scaleY, 100 * scaleX, 20 * scaleY) - ) - .Fill( - new GraphicsOptions { Antialias = true, ColorBlendingMode = blending, AlphaCompositionMode = composition }, - Color.HotPink, - new Rectangle(20 * scaleX, 0 * scaleY, 30 * scaleX, 100 * scaleY)) - ); - - VerifyImage(provider, blending, composition, img); - } - } - - [Theory] - [WithBlankImages(nameof(modes), 250, 250, PixelTypes.Rgba32)] - public void _1DarkBlueRect_2BlendHotPinkRect_3BlendTransparentEllipse( - TestImageProvider provider, - PixelColorBlendingMode blending, - PixelAlphaCompositionMode composition) - where TPixel : struct, IPixel - { - using (Image img = provider.GetImage()) - { - int scaleX = img.Width / 100; - int scaleY = img.Height / 100; - img.Mutate( - x => x.Fill( - Color.DarkBlue, - new Rectangle(0 * scaleX, 40 * scaleY, 100 * scaleX, 20 * scaleY))); - img.Mutate( - x => x.Fill( - new GraphicsOptions { Antialias = true, ColorBlendingMode = blending, AlphaCompositionMode = composition }, - Color.HotPink, - new Rectangle(20 * scaleX, 0 * scaleY, 30 * scaleX, 100 * scaleY))); - img.Mutate( - x => x.Fill( - new GraphicsOptions { Antialias = true, ColorBlendingMode = blending, AlphaCompositionMode = composition }, - Color.Transparent, - new Shapes.EllipsePolygon(40 * scaleX, 50 * scaleY, 50 * scaleX, 50 * scaleY)) - ); - - VerifyImage(provider, blending, composition, img); - } - } - - [Theory] - [WithBlankImages(nameof(modes), 250, 250, PixelTypes.Rgba32)] - public void _1DarkBlueRect_2BlendHotPinkRect_3BlendSemiTransparentRedEllipse( - TestImageProvider provider, - PixelColorBlendingMode blending, - PixelAlphaCompositionMode composition) - where TPixel : struct, IPixel - { - using (Image img = provider.GetImage()) - { - int scaleX = (img.Width / 100); - int scaleY = (img.Height / 100); - img.Mutate( - x => x.Fill( - Color.DarkBlue, - new Rectangle(0 * scaleX, 40, 100 * scaleX, 20 * scaleY))); - img.Mutate( - x => x.Fill( - new GraphicsOptions { Antialias = true, ColorBlendingMode = blending, AlphaCompositionMode = composition }, - Color.HotPink, - new Rectangle(20 * scaleX, 0, 30 * scaleX, 100 * scaleY))); - - var transparentRed = Color.Red.WithAlpha(0.5f); - - img.Mutate( - x => x.Fill( - new GraphicsOptions { Antialias = true, ColorBlendingMode = blending, AlphaCompositionMode = composition }, - transparentRed, - new Shapes.EllipsePolygon(40 * scaleX, 50 * scaleY, 50 * scaleX, 50 * scaleY)) - ); - - VerifyImage(provider, blending, composition, img); ; - } - } - - [Theory] - [WithBlankImages(nameof(modes), 250, 250, PixelTypes.Rgba32)] - public void _1DarkBlueRect_2BlendBlackEllipse( - TestImageProvider provider, - PixelColorBlendingMode blending, - PixelAlphaCompositionMode composition) - where TPixel : struct, IPixel - { - using (Image dstImg = provider.GetImage(), srcImg = provider.GetImage()) - { - int scaleX = (dstImg.Width / 100); - int scaleY = (dstImg.Height / 100); - - dstImg.Mutate( - x => x.Fill( - Color.DarkBlue, - new Rectangle(0 * scaleX, 40 * scaleY, 100 * scaleX, 20 * scaleY))); - - srcImg.Mutate( - x => x.Fill( - Color.Black, - new Shapes.EllipsePolygon(40 * scaleX, 50 * scaleY, 50 * scaleX, 50 * scaleY))); - - dstImg.Mutate( - x => x.DrawImage(srcImg, new GraphicsOptions { Antialias = true, ColorBlendingMode = blending, AlphaCompositionMode = composition }) - ); - - VerifyImage(provider, blending, composition, dstImg); - } - } - - private static void VerifyImage( - TestImageProvider provider, - PixelColorBlendingMode blending, - PixelAlphaCompositionMode composition, - Image img) - where TPixel : struct, IPixel - { - img.DebugSave( - provider, - new { composition, blending }, - appendPixelTypeToFileName: false, - appendSourceFileOrDescription: false); - - var comparer = ImageComparer.TolerantPercentage(0.01f, 3); - img.CompareFirstFrameToReferenceOutput(comparer, - provider, - new { composition, blending }, - appendPixelTypeToFileName: false, - appendSourceFileOrDescription: false); - } - } -} diff --git a/tests/ImageSharp.Tests/Drawing/Text/DrawText.cs b/tests/ImageSharp.Tests/Drawing/Text/DrawText.cs deleted file mode 100644 index 2a39e18cb..000000000 --- a/tests/ImageSharp.Tests/Drawing/Text/DrawText.cs +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Numerics; -using SixLabors.Fonts; -using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Processing.Processors.Text; -using SixLabors.ImageSharp.Tests.Processing; -using SixLabors.Primitives; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Drawing.Text -{ - public class DrawText : BaseImageOperationsExtensionTest - { - private readonly FontCollection FontCollection; - - private readonly Font Font; - - public DrawText() - { - this.FontCollection = new FontCollection(); - this.Font = this.FontCollection.Install(TestFontUtilities.GetPath("SixLaborsSampleAB.woff")).CreateFont(12); - } - - [Fact] - public void FillsForEachACharacterWhenBrushSetAndNotPen() - { - this.operations.DrawText( - new TextGraphicsOptions { Antialias = true }, - "123", - this.Font, - Brushes.Solid(Color.Red), - null, - Vector2.Zero); - - this.Verify(0); - } - - [Fact] - public void FillsForEachACharacterWhenBrushSetAndNotPenDefaultOptions() - { - this.operations.DrawText("123", this.Font, Brushes.Solid(Color.Red), null, Vector2.Zero); - - this.Verify(0); - } - - [Fact] - public void FillsForEachACharacterWhenBrushSet() - { - this.operations.DrawText(new TextGraphicsOptions { Antialias = true }, "123", this.Font, Brushes.Solid(Color.Red), Vector2.Zero); - - this.Verify(0); - } - - [Fact] - public void FillsForEachACharacterWhenBrushSetDefaultOptions() - { - this.operations.DrawText("123", this.Font, Brushes.Solid(Color.Red), Vector2.Zero); - - this.Verify(0); - } - - [Fact] - public void FillsForEachACharacterWhenColorSet() - { - this.operations.DrawText(new TextGraphicsOptions { Antialias = true }, "123", this.Font, Color.Red, Vector2.Zero); - - var processor = this.Verify(0); - - SolidBrush brush = Assert.IsType(processor.Brush); - Assert.Equal(Color.Red, brush.Color); - } - - [Fact] - public void FillsForEachACharacterWhenColorSetDefaultOptions() - { - this.operations.DrawText("123", this.Font, Color.Red, Vector2.Zero); - - var processor = this.Verify(0); - - SolidBrush brush = Assert.IsType(processor.Brush); - Assert.Equal(Color.Red, brush.Color); - } - - [Fact] - public void DrawForEachACharacterWhenPenSetAndNotBrush() - { - this.operations.DrawText( - new TextGraphicsOptions { Antialias = true }, - "123", - this.Font, - null, - Pens.Dash(Color.Red, 1), - Vector2.Zero); - - this.Verify(0); - } - - [Fact] - public void DrawForEachACharacterWhenPenSetAndNotBrushDefaultOptions() - { - this.operations.DrawText("123", this.Font, null, Pens.Dash(Color.Red, 1), Vector2.Zero); - - this.Verify(0); - } - - [Fact] - public void DrawForEachACharacterWhenPenSet() - { - this.operations.DrawText(new TextGraphicsOptions { Antialias = true }, "123", this.Font, Pens.Dash(Color.Red, 1), Vector2.Zero); - - this.Verify(0); - } - - [Fact] - public void DrawForEachACharacterWhenPenSetDefaultOptions() - { - this.operations.DrawText("123", this.Font, Pens.Dash(Color.Red, 1), Vector2.Zero); - - var processor = this.Verify(0); - - Assert.Equal("123", processor.Text); - Assert.Equal(this.Font, processor.Font); - var penBrush = Assert.IsType(processor.Pen.StrokeFill); - Assert.Equal(Color.Red, penBrush.Color); - Assert.Equal(1, processor.Pen.StrokeWidth); - Assert.Equal(PointF.Empty, processor.Location); - } - - [Fact] - public void DrawForEachACharacterWhenPenSetAndFillFroEachWhenBrushSet() - { - this.operations.DrawText( - new TextGraphicsOptions { Antialias = true }, - "123", - this.Font, - Brushes.Solid(Color.Red), - Pens.Dash(Color.Red, 1), - Vector2.Zero); - - var processor = this.Verify(0); - - Assert.Equal("123", processor.Text); - Assert.Equal(this.Font, processor.Font); - var brush = Assert.IsType(processor.Brush); - Assert.Equal(Color.Red, brush.Color); - Assert.Equal(PointF.Empty, processor.Location); - var penBrush = Assert.IsType(processor.Pen.StrokeFill); - Assert.Equal(Color.Red, penBrush.Color); - Assert.Equal(1, processor.Pen.StrokeWidth); - } - } -} diff --git a/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs b/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs deleted file mode 100644 index 281a51650..000000000 --- a/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs +++ /dev/null @@ -1,265 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Linq; -using System.Text; -using SixLabors.Fonts; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; -using SixLabors.Primitives; - -using Xunit; -using Xunit.Abstractions; - -// ReSharper disable InconsistentNaming - -namespace SixLabors.ImageSharp.Tests.Drawing.Text -{ - [GroupOutput("Drawing/Text")] - public class DrawTextOnImageTests - { - private const string AB = "AB\nAB"; - - private const string TestText = "Sphinx of black quartz, judge my vow\n0123456789"; - - public static ImageComparer TextDrawingComparer = ImageComparer.TolerantPercentage(1e-5f); - public static ImageComparer OutlinedTextDrawingComparer = ImageComparer.TolerantPercentage(5e-4f); - - public DrawTextOnImageTests(ITestOutputHelper output) - { - this.Output = output; - } - - private ITestOutputHelper Output { get; } - - [Theory] - [WithSolidFilledImages(276, 336, "White", PixelTypes.Rgba32)] - public void DoesntThrowExceptionWhenOverlappingRightEdge_Issue688(TestImageProvider provider) - where TPixel : struct, IPixel - { - Font font = CreateFont("OpenSans-Regular.ttf", 36); - var color = Color.Black; - var text = "A short piece of text"; - - using (var img = provider.GetImage()) - { - // measure the text size - SizeF size = TextMeasurer.Measure(text, new RendererOptions(font)); - - //find out how much we need to scale the text to fill the space (up or down) - float scalingFactor = Math.Min(img.Width / size.Width, img.Height / size.Height); - - //create a new font - var scaledFont = new Font(font, scalingFactor * font.Size); - - var center = new PointF(img.Width / 2, img.Height / 2); - var textGraphicOptions = new TextGraphicsOptions - { - Antialias = true, - HorizontalAlignment = HorizontalAlignment.Center, - VerticalAlignment = VerticalAlignment.Center - }; - - img.Mutate(i => i.DrawText(textGraphicOptions, text, scaledFont, color, center)); - } - } - - [Theory] - [WithSolidFilledImages(1500, 500, "White", PixelTypes.Rgba32)] - public void DoesntThrowExceptionWhenOverlappingRightEdge_Issue688_2(TestImageProvider provider) - where TPixel : struct, IPixel - { - using (Image img = provider.GetImage()) - { - Font font = CreateFont("OpenSans-Regular.ttf", 39); - string text = new string('a', 10000); // exception - // string text = "Hello"; // no exception - Rgba32 color = Rgba32.Black; - var point = new PointF(100, 100); - - img.Mutate(ctx => ctx.DrawText(text, font, color, point)); - } - } - - - [Theory] - [WithSolidFilledImages(200, 100, "White", PixelTypes.Rgba32, 50, 0, 0, "SixLaborsSampleAB.woff", AB)] - [WithSolidFilledImages(900, 100, "White", PixelTypes.Rgba32, 50, 0, 0, "OpenSans-Regular.ttf", TestText)] - [WithSolidFilledImages(400, 40, "White", PixelTypes.Rgba32, 20, 0, 0, "OpenSans-Regular.ttf", TestText)] - [WithSolidFilledImages(1100, 200, "White", PixelTypes.Rgba32, 50, 150, 100, "OpenSans-Regular.ttf", TestText)] - public void FontShapesAreRenderedCorrectly( - TestImageProvider provider, - int fontSize, - int x, - int y, - string fontName, - string text) - where TPixel : struct, IPixel - { - Font font = CreateFont(fontName, fontSize); - var color = Color.Black; - - provider.VerifyOperation( - TextDrawingComparer, - img => - { - img.Mutate(c => c.DrawText(text, new Font(font, fontSize), color, new PointF(x, y))); - }, - $"{fontName}-{fontSize}-{ToTestOutputDisplayText(text)}-({x},{y})", - appendPixelTypeToFileName: false, - appendSourceFileOrDescription: true); - } - - /// - /// Based on: - /// https://github.com/SixLabors/ImageSharp/issues/572 - /// - [Theory] - [WithSolidFilledImages(2480, 3508, "White", PixelTypes.Rgba32)] - public void FontShapesAreRenderedCorrectly_LargeText( - TestImageProvider provider) - where TPixel : struct, IPixel - { - Font font = CreateFont("OpenSans-Regular.ttf", 36); - - var sb = new StringBuilder(); - string str = Repeat(" ", 78) + "THISISTESTWORDSTHISISTESTWORDSTHISISTESTWORDSTHISISTESTWORDSTHISISTESTWORDS"; - sb.Append(str); - - string newLines = Repeat(Environment.NewLine, 80); - sb.Append(newLines); - - for (int i = 0; i < 10; i++) - { - sb.AppendLine(str); - } - - var textOptions = new TextGraphicsOptions - { - Antialias = true, - ApplyKerning = true, - VerticalAlignment = VerticalAlignment.Top, - HorizontalAlignment = HorizontalAlignment.Left, - }; - - var color = Color.Black; - - // Based on the reported 0.0270% difference with AccuracyMultiple = 8 - // We should avoid quality regressions leading to higher difference! - var comparer = ImageComparer.TolerantPercentage(0.03f); - - provider.VerifyOperation( - comparer, - img => - { - img.Mutate(c => c.DrawText(textOptions, sb.ToString(), font, color, new PointF(10, 5))); - }, - false, - false); - } - - [Theory] - [WithSolidFilledImages(200, 100, "White", PixelTypes.Rgba32, 50, 0, 0, "SixLaborsSampleAB.woff", AB)] - [WithSolidFilledImages(900, 100, "White", PixelTypes.Rgba32, 50, 0, 0, "OpenSans-Regular.ttf", TestText)] - [WithSolidFilledImages(1100, 200, "White", PixelTypes.Rgba32, 50, 150, 100, "OpenSans-Regular.ttf", TestText)] - public void FontShapesAreRenderedCorrectlyWithAPen( - TestImageProvider provider, - int fontSize, - int x, - int y, - string fontName, - string text) - where TPixel : struct, IPixel - { - Font font = CreateFont(fontName, fontSize); - var color = Color.Black; - - provider.VerifyOperation( - OutlinedTextDrawingComparer, - img => - { - img.Mutate(c => c.DrawText(text, new Font(font, fontSize), null, Pens.Solid(color, 1), new PointF(x, y))); - }, - $"pen_{fontName}-{fontSize}-{ToTestOutputDisplayText(text)}-({x},{y})", - appendPixelTypeToFileName: false, - appendSourceFileOrDescription: true); - } - - [Theory] - [WithSolidFilledImages(200, 100, "White", PixelTypes.Rgba32, 50, 0, 0, "SixLaborsSampleAB.woff", AB)] - [WithSolidFilledImages(900, 100, "White", PixelTypes.Rgba32, 50, 0, 0, "OpenSans-Regular.ttf", TestText)] - [WithSolidFilledImages(1100, 200, "White", PixelTypes.Rgba32, 50, 150, 100, "OpenSans-Regular.ttf", TestText)] - public void FontShapesAreRenderedCorrectlyWithAPenPatterned( - TestImageProvider provider, - int fontSize, - int x, - int y, - string fontName, - string text) - where TPixel : struct, IPixel - { - Font font = CreateFont(fontName, fontSize); - var color = Color.Black; - - provider.VerifyOperation( - OutlinedTextDrawingComparer, - img => - { - img.Mutate(c => c.DrawText(text, new Font(font, fontSize), null, Pens.DashDot(color, 3), new PointF(x, y))); - }, - $"pen_{fontName}-{fontSize}-{ToTestOutputDisplayText(text)}-({x},{y})", - appendPixelTypeToFileName: false, - appendSourceFileOrDescription: true); - } - - [Theory] - [WithSolidFilledImages(1000, 1500, "White", PixelTypes.Rgba32, "OpenSans-Regular.ttf")] - public void TextPositioningIsRobust(TestImageProvider provider, string fontName) - where TPixel : struct, IPixel - { - Font font = CreateFont(fontName, 30); - - string text = Repeat("Beware the Jabberwock, my son! The jaws that bite, the claws that catch! Beware the Jubjub bird, and shun The frumious Bandersnatch!\n", - 20); - var textOptions = new TextGraphicsOptions - { - Antialias = true, - WrapTextWidth = 1000 - }; - - string details = fontName.Replace(" ", ""); - - // Based on the reported 0.1755% difference with AccuracyMultiple = 8 - // We should avoid quality regressions leading to higher difference! - var comparer = ImageComparer.TolerantPercentage(0.2f); - - provider.RunValidatingProcessorTest( - x => x.DrawText(textOptions, text, font, Color.Black, new PointF(10, 50)), - details, - comparer, - appendPixelTypeToFileName: false, - appendSourceFileOrDescription: false); - } - - private static string Repeat(string str, int times) => string.Concat(Enumerable.Repeat(str, times)); - - private static string ToTestOutputDisplayText(string text) - { - string fnDisplayText = text.Replace("\n", ""); - fnDisplayText = fnDisplayText.Substring(0, Math.Min(fnDisplayText.Length, 4)); - return fnDisplayText; - } - - private static Font CreateFont(string fontName, int size) - { - var fontCollection = new FontCollection(); - string fontPath = TestFontUtilities.GetPath(fontName); - Font font = fontCollection.Install(fontPath).CreateFont(size); - return font; - } - - - } -} diff --git a/tests/ImageSharp.Tests/Drawing/Text/TextGraphicsOptionsTests.cs b/tests/ImageSharp.Tests/Drawing/Text/TextGraphicsOptionsTests.cs deleted file mode 100644 index a59afb271..000000000 --- a/tests/ImageSharp.Tests/Drawing/Text/TextGraphicsOptionsTests.cs +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.Fonts; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; - -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Drawing.Text -{ - public class TextGraphicsOptionsTests - { - private readonly TextGraphicsOptions newTextGraphicsOptions = new TextGraphicsOptions(); - private readonly TextGraphicsOptions cloneTextGraphicsOptions = new TextGraphicsOptions().DeepClone(); - - [Fact] - public void CloneTextGraphicsOptionsIsNotNull() => Assert.True(this.cloneTextGraphicsOptions != null); - - [Fact] - public void DefaultTextGraphicsOptionsAntialias() - { - Assert.True(this.newTextGraphicsOptions.Antialias); - Assert.True(this.cloneTextGraphicsOptions.Antialias); - } - - [Fact] - public void DefaultTextGraphicsOptionsAntialiasSuppixelDepth() - { - const int Expected = 16; - Assert.Equal(Expected, this.newTextGraphicsOptions.AntialiasSubpixelDepth); - Assert.Equal(Expected, this.cloneTextGraphicsOptions.AntialiasSubpixelDepth); - } - - [Fact] - public void DefaultTextGraphicsOptionsBlendPercentage() - { - const float Expected = 1F; - Assert.Equal(Expected, this.newTextGraphicsOptions.BlendPercentage); - Assert.Equal(Expected, this.cloneTextGraphicsOptions.BlendPercentage); - } - - [Fact] - public void DefaultTextGraphicsOptionsColorBlendingMode() - { - const PixelColorBlendingMode Expected = PixelColorBlendingMode.Normal; - Assert.Equal(Expected, this.newTextGraphicsOptions.ColorBlendingMode); - Assert.Equal(Expected, this.cloneTextGraphicsOptions.ColorBlendingMode); - } - - [Fact] - public void DefaultTextGraphicsOptionsAlphaCompositionMode() - { - const PixelAlphaCompositionMode Expected = PixelAlphaCompositionMode.SrcOver; - Assert.Equal(Expected, this.newTextGraphicsOptions.AlphaCompositionMode); - Assert.Equal(Expected, this.cloneTextGraphicsOptions.AlphaCompositionMode); - } - - [Fact] - public void DefaultTextGraphicsOptionsApplyKerning() - { - const bool Expected = true; - Assert.Equal(Expected, this.newTextGraphicsOptions.ApplyKerning); - Assert.Equal(Expected, this.cloneTextGraphicsOptions.ApplyKerning); - } - - [Fact] - public void DefaultTextGraphicsOptionsHorizontalAlignment() - { - const HorizontalAlignment Expected = HorizontalAlignment.Left; - Assert.Equal(Expected, this.newTextGraphicsOptions.HorizontalAlignment); - Assert.Equal(Expected, this.cloneTextGraphicsOptions.HorizontalAlignment); - } - - [Fact] - public void DefaultTextGraphicsOptionsVerticalAlignment() - { - const VerticalAlignment Expected = VerticalAlignment.Top; - Assert.Equal(Expected, this.newTextGraphicsOptions.VerticalAlignment); - Assert.Equal(Expected, this.cloneTextGraphicsOptions.VerticalAlignment); - } - - [Fact] - public void DefaultTextGraphicsOptionsDpiX() - { - const float Expected = 72F; - Assert.Equal(Expected, this.newTextGraphicsOptions.DpiX); - Assert.Equal(Expected, this.cloneTextGraphicsOptions.DpiX); - } - - [Fact] - public void DefaultTextGraphicsOptionsDpiY() - { - const float Expected = 72F; - Assert.Equal(Expected, this.newTextGraphicsOptions.DpiY); - Assert.Equal(Expected, this.cloneTextGraphicsOptions.DpiY); - } - - [Fact] - public void DefaultTextGraphicsOptionsTabWidth() - { - const float Expected = 4F; - Assert.Equal(Expected, this.newTextGraphicsOptions.TabWidth); - Assert.Equal(Expected, this.cloneTextGraphicsOptions.TabWidth); - } - - [Fact] - public void DefaultTextGraphicsOptionsWrapTextWidth() - { - const float Expected = 0F; - Assert.Equal(Expected, this.newTextGraphicsOptions.WrapTextWidth); - Assert.Equal(Expected, this.cloneTextGraphicsOptions.WrapTextWidth); - } - - [Fact] - public void NonDefaultClone() - { - var expected = new TextGraphicsOptions - { - AlphaCompositionMode = PixelAlphaCompositionMode.DestAtop, - Antialias = false, - AntialiasSubpixelDepth = 23, - ApplyKerning = false, - BlendPercentage = .25F, - ColorBlendingMode = PixelColorBlendingMode.HardLight, - DpiX = 46F, - DpiY = 52F, - HorizontalAlignment = HorizontalAlignment.Center, - TabWidth = 3F, - VerticalAlignment = VerticalAlignment.Bottom, - WrapTextWidth = 42F - }; - - TextGraphicsOptions actual = expected.DeepClone(); - - Assert.Equal(expected.AlphaCompositionMode, actual.AlphaCompositionMode); - Assert.Equal(expected.Antialias, actual.Antialias); - Assert.Equal(expected.AntialiasSubpixelDepth, actual.AntialiasSubpixelDepth); - Assert.Equal(expected.ApplyKerning, actual.ApplyKerning); - Assert.Equal(expected.BlendPercentage, actual.BlendPercentage); - Assert.Equal(expected.ColorBlendingMode, actual.ColorBlendingMode); - Assert.Equal(expected.DpiX, actual.DpiX); - Assert.Equal(expected.DpiY, actual.DpiY); - Assert.Equal(expected.HorizontalAlignment, actual.HorizontalAlignment); - Assert.Equal(expected.TabWidth, actual.TabWidth); - Assert.Equal(expected.VerticalAlignment, actual.VerticalAlignment); - Assert.Equal(expected.WrapTextWidth, actual.WrapTextWidth); - } - - [Fact] - public void CloneIsDeep() - { - var expected = new TextGraphicsOptions(); - TextGraphicsOptions actual = expected.DeepClone(); - - actual.AlphaCompositionMode = PixelAlphaCompositionMode.DestAtop; - actual.Antialias = false; - actual.AntialiasSubpixelDepth = 23; - actual.ApplyKerning = false; - actual.BlendPercentage = .25F; - actual.ColorBlendingMode = PixelColorBlendingMode.HardLight; - actual.DpiX = 46F; - actual.DpiY = 52F; - actual.HorizontalAlignment = HorizontalAlignment.Center; - actual.TabWidth = 3F; - actual.VerticalAlignment = VerticalAlignment.Bottom; - actual.WrapTextWidth = 42F; - - Assert.NotEqual(expected.AlphaCompositionMode, actual.AlphaCompositionMode); - Assert.NotEqual(expected.Antialias, actual.Antialias); - Assert.NotEqual(expected.AntialiasSubpixelDepth, actual.AntialiasSubpixelDepth); - Assert.NotEqual(expected.ApplyKerning, actual.ApplyKerning); - Assert.NotEqual(expected.BlendPercentage, actual.BlendPercentage); - Assert.NotEqual(expected.ColorBlendingMode, actual.ColorBlendingMode); - Assert.NotEqual(expected.DpiX, actual.DpiX); - Assert.NotEqual(expected.DpiY, actual.DpiY); - Assert.NotEqual(expected.HorizontalAlignment, actual.HorizontalAlignment); - Assert.NotEqual(expected.TabWidth, actual.TabWidth); - Assert.NotEqual(expected.VerticalAlignment, actual.VerticalAlignment); - Assert.NotEqual(expected.WrapTextWidth, actual.WrapTextWidth); - } - - [Fact] - public void ExplicitCastOfGraphicsOptions() - { - TextGraphicsOptions textOptions = new GraphicsOptions - { - Antialias = false, - AntialiasSubpixelDepth = 99 - }; - - Assert.False(textOptions.Antialias); - Assert.Equal(99, textOptions.AntialiasSubpixelDepth); - } - - [Fact] - public void ImplicitCastToGraphicsOptions() - { - var textOptions = new TextGraphicsOptions - { - Antialias = false, - AntialiasSubpixelDepth = 99 - }; - - var opt = (GraphicsOptions)textOptions; - - Assert.False(opt.Antialias); - Assert.Equal(99, opt.AntialiasSubpixelDepth); - } - } -} diff --git a/tests/ImageSharp.Tests/Drawing/Utils/QuickSortTests.cs b/tests/ImageSharp.Tests/Drawing/Utils/QuickSortTests.cs deleted file mode 100644 index 5ad7a1248..000000000 --- a/tests/ImageSharp.Tests/Drawing/Utils/QuickSortTests.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -namespace SixLabors.ImageSharp.Tests.Drawing.Utils -{ - using System; - using System.Linq; - - using SixLabors.ImageSharp.Utils; - - using Xunit; - - public class QuickSortTests - { - public static readonly TheoryData Data = new TheoryData - { - new float[]{ 3, 2, 1 }, - new float[0], - new float[] { 42}, - new float[] { 1, 2}, - new float[] { 2, 1}, - new float[] { 5, 1, 2, 3, 0} - }; - - [Theory] - [MemberData(nameof(Data))] - public void Sort(float[] data) - { - float[] expected = data.ToArray(); - - Array.Sort(expected); - - QuickSort.Sort(data); - - Assert.Equal(expected, data); - } - - [Fact] - public void SortSlice() - { - float[] data = { 3, 2, 1, 0, -1 }; - - Span slice = data.AsSpan(1, 3); - QuickSort.Sort(slice); - float[] actual = slice.ToArray(); - float[] expected = { 0, 1, 2 }; - - Assert.Equal(actual, expected); - } - } -} diff --git a/tests/ImageSharp.Tests/GraphicsOptionsTests.cs b/tests/ImageSharp.Tests/GraphicsOptionsTests.cs index 69f904f1c..e4892e561 100644 --- a/tests/ImageSharp.Tests/GraphicsOptionsTests.cs +++ b/tests/ImageSharp.Tests/GraphicsOptionsTests.cs @@ -86,15 +86,5 @@ namespace SixLabors.ImageSharp.Tests Assert.NotEqual(expected, actual, graphicsOptionsComparer); } - - [Fact] - public void IsOpaqueColor() - { - Assert.True(new GraphicsOptions().IsOpaqueColorWithoutBlending(Rgba32.Red)); - Assert.False(new GraphicsOptions { BlendPercentage = .5F }.IsOpaqueColorWithoutBlending(Rgba32.Red)); - Assert.False(new GraphicsOptions().IsOpaqueColorWithoutBlending(Rgba32.Transparent)); - Assert.False(new GraphicsOptions { ColorBlendingMode = PixelColorBlendingMode.Lighten, BlendPercentage = 1F }.IsOpaqueColorWithoutBlending(Rgba32.Red)); - Assert.False(new GraphicsOptions { ColorBlendingMode = PixelColorBlendingMode.Normal, AlphaCompositionMode = PixelAlphaCompositionMode.DestOver, BlendPercentage = 1f }.IsOpaqueColorWithoutBlending(Rgba32.Red)); - } } } diff --git a/tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs b/tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs index ea9957314..63c2e57c8 100644 --- a/tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs +++ b/tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System; @@ -11,7 +11,6 @@ using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Common.Helpers; using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Shapes; using SixLabors.ImageSharp.Processing; using Xunit; @@ -60,13 +59,13 @@ namespace SixLabors.ImageSharp.Tests { this.bitmap.UnlockBits(this.bmpData); } - + this.IsDisposed = true; } public override unsafe Span GetSpan() { - void* ptr = (void*) this.bmpData.Scan0; + void* ptr = (void*)this.bmpData.Scan0; return new Span(ptr, this.length); } @@ -119,7 +118,11 @@ namespace SixLabors.ImageSharp.Tests using (var image = Image.WrapMemory(memory, bmp.Width, bmp.Height)) { Assert.Equal(memory, image.GetPixelMemory()); - image.Mutate(c => c.Fill(bg).Fill(fg, new RectangularPolygon(10, 10, 10, 10))); + image.GetPixelSpan().Fill(bg); + for (var i = 10; i < 20; i++) + { + image.GetPixelRowSpan(i).Slice(10, 10).Fill(fg); + } } Assert.False(memoryManager.IsDisposed); @@ -150,7 +153,12 @@ namespace SixLabors.ImageSharp.Tests using (var image = Image.WrapMemory(memoryManager, bmp.Width, bmp.Height)) { Assert.Equal(memoryManager.Memory, image.GetPixelMemory()); - image.Mutate(c => c.Fill(bg).Fill(fg, new RectangularPolygon(10, 10, 10, 10))); + + image.GetPixelSpan().Fill(bg); + for (var i = 10; i < 20; i++) + { + image.GetPixelRowSpan(i).Slice(10, 10).Fill(fg); + } } Assert.True(memoryManager.IsDisposed); @@ -167,4 +175,4 @@ namespace SixLabors.ImageSharp.Tests !TestEnvironment.Is64BitProcess || TestHelpers.ImageSharpBuiltAgainst != "netcoreapp2.1"; } } -} \ No newline at end of file +} diff --git a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj index 1ac5f8085..28867ddc2 100644 --- a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj +++ b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj @@ -38,7 +38,6 @@ - diff --git a/tests/ImageSharp.Tests/Issues/Issue412.cs b/tests/ImageSharp.Tests/Issues/Issue412.cs deleted file mode 100644 index 53c65b643..000000000 --- a/tests/ImageSharp.Tests/Issues/Issue412.cs +++ /dev/null @@ -1,51 +0,0 @@ -using SixLabors.Primitives; - -using Xunit; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; - -namespace SixLabors.ImageSharp.Tests.Issues -{ - public class Issue412 - { - [Theory] - [WithBlankImages(40, 30, PixelTypes.Rgba32)] - public void AllPixelsExpectedToBeRedWhenAntialiasedDisabled(TestImageProvider provider) where TPixel : struct, IPixel - { - using (Image image = provider.GetImage()) - { - image.Mutate( - context => - { - for (var i = 0; i < 40; ++i) - { - context.DrawLines( - new GraphicsOptions { Antialias = false }, - Color.Black, - 1, - new PointF(i, 0.1066f), - new PointF(i, 10.1066f)); - - context.DrawLines( - new GraphicsOptions { Antialias = false }, - Color.Red, - 1, - new PointF(i, 15.1066f), - new PointF(i, 25.1066f)); - } - }); - - image.DebugSave(provider); - for (var y = 15; y < 25; y++) - { - for (var x = 0; x < 40; x++) - { - TPixel red = Color.Red.ToPixel(); - - Assert.True(red.Equals(image[x, y]), $"expected {Color.Red} but found {image[x, y]} at [{x}, {y}]"); - } - } - } - } - } -} diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/SolidProvider.cs b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/SolidProvider.cs index 88b30ce34..e44de307f 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/SolidProvider.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/SolidProvider.cs @@ -1,7 +1,8 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using Xunit.Abstractions; @@ -55,7 +56,7 @@ namespace SixLabors.ImageSharp.Tests Image image = base.GetImage(); Color color = new Rgba32(this.r, this.g, this.b, this.a); - image.Mutate(x => x.Fill(color)); + image.GetPixelSpan().Fill(color.ToPixel()); return image; } @@ -78,4 +79,4 @@ namespace SixLabors.ImageSharp.Tests } } } -} \ No newline at end of file +} diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs index 096f78299..567a1b030 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System; @@ -33,28 +33,28 @@ namespace SixLabors.ImageSharp.Tests Assert.True(Directory.Exists(path)); } - /// - /// We need this test to make sure that the netcoreapp2.1 test execution actually covers the netcoreapp2.1 build configuration of ImageSharp. - /// - [Fact] - public void ImageSharpAssemblyUnderTest_MatchesExpectedTargetFramework() - { - this.Output.WriteLine("NetCoreVersion: " + TestEnvironment.NetCoreVersion); - this.Output.WriteLine("ImageSharpBuiltAgainst: " + TestHelpers.ImageSharpBuiltAgainst); - - if (string.IsNullOrEmpty(TestEnvironment.NetCoreVersion)) - { - this.Output.WriteLine("Not running under .NET Core!"); - } - else if (TestEnvironment.NetCoreVersion.StartsWith("2.1")) - { - Assert.Equal("netcoreapp2.1", TestHelpers.ImageSharpBuiltAgainst); - } - else - { - Assert.Equal("netstandard2.0", TestHelpers.ImageSharpBuiltAgainst); - } - } + ///// + ///// We need this test to make sure that the netcoreapp2.1 test execution actually covers the netcoreapp2.1 build configuration of ImageSharp. + ///// + //[Fact] + //public void ImageSharpAssemblyUnderTest_MatchesExpectedTargetFramework() + //{ + // this.Output.WriteLine("NetCoreVersion: " + TestEnvironment.NetCoreVersion); + // this.Output.WriteLine("ImageSharpBuiltAgainst: " + TestHelpers.ImageSharpBuiltAgainst); + + // if (string.IsNullOrEmpty(TestEnvironment.NetCoreVersion)) + // { + // this.Output.WriteLine("Not running under .NET Core!"); + // } + // else if (TestEnvironment.NetCoreVersion.StartsWith("2.1")) + // { + // Assert.Equal("netcoreapp2.1", TestHelpers.ImageSharpBuiltAgainst); + // } + // else + // { + // Assert.Equal("netstandard2.0", TestHelpers.ImageSharpBuiltAgainst); + // } + //} [Fact] public void SolutionDirectoryFullPath() From 16a0322ec04260dc285fb610efbe587091447e9a Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 14 Jan 2020 10:45:56 +1100 Subject: [PATCH 2/2] Move DrawImage processors and extensions. --- .../Extensions/Drawing}/DrawImageExtensions.cs | 0 .../Processing/Processors/Drawing/DrawImageProcessor.cs | 0 .../Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename src/ImageSharp/{Drawing/Processing/Extensions => Processing/Extensions/Drawing}/DrawImageExtensions.cs (100%) rename src/ImageSharp/{Drawing => }/Processing/Processors/Drawing/DrawImageProcessor.cs (100%) rename src/ImageSharp/{Drawing => }/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs (100%) diff --git a/src/ImageSharp/Drawing/Processing/Extensions/DrawImageExtensions.cs b/src/ImageSharp/Processing/Extensions/Drawing/DrawImageExtensions.cs similarity index 100% rename from src/ImageSharp/Drawing/Processing/Extensions/DrawImageExtensions.cs rename to src/ImageSharp/Processing/Extensions/Drawing/DrawImageExtensions.cs diff --git a/src/ImageSharp/Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs b/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor.cs similarity index 100% rename from src/ImageSharp/Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs rename to src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor.cs diff --git a/src/ImageSharp/Drawing/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs b/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs similarity index 100% rename from src/ImageSharp/Drawing/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs rename to src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs