Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
2e76417
Quickly integrate SixLabors.PolygonClipper
Sep 30, 2025
6c6ff30
First draft of PolygonOffsette
stefannikolei Oct 7, 2025
8f9696f
Fix ClipTest.Issue250
stefannikolei Oct 7, 2025
087f480
Wire up factory
JimBobSquarePants Oct 8, 2025
8e7164e
Merge branch 'sn/integrate-polygonclipper' of https://github.com/stef…
JimBobSquarePants Oct 8, 2025
ef89dd0
Use Vertex.Cross
JimBobSquarePants Oct 8, 2025
26ead24
Merge remote-tracking branch 'upstream/main' into sn/integrate-polygo…
JimBobSquarePants Oct 30, 2025
5b2179b
Replace PolygonOffsetter with PolygonStroker from AGG
JimBobSquarePants Oct 31, 2025
bf57cfe
Update ISimplePath.cs
JimBobSquarePants Oct 31, 2025
f976353
Update namespace
JimBobSquarePants Oct 31, 2025
de7fa43
Merge remote-tracking branch 'upstream/main' into sn/integrate-polygo…
JimBobSquarePants Feb 4, 2026
ac98cc6
Update ImageSharp.Drawing.sln to Visual Studio 18
JimBobSquarePants Feb 4, 2026
33afe06
Update package references in ImageSharp.Drawing.csproj
JimBobSquarePants Feb 4, 2026
20f6460
Only clip when we need to
JimBobSquarePants Feb 4, 2026
1174d90
Do not use polygonclipper
JimBobSquarePants Feb 4, 2026
52312a1
Clean PolygonClipperUtilities
JimBobSquarePants Feb 5, 2026
49aaf25
Fix build, more cleanup
JimBobSquarePants Feb 5, 2026
1006631
Document PolygonClipper
JimBobSquarePants Feb 5, 2026
3b1b88d
Handle degenerate inbound path.
JimBobSquarePants Feb 5, 2026
f41dc74
Remove unnecessary checks
JimBobSquarePants Feb 5, 2026
6b42ee3
Use scale appropriate tolerances
JimBobSquarePants Feb 5, 2026
e5ada72
Use PolygonClipper
JimBobSquarePants Feb 17, 2026
a8be3f9
Use non-zero as default intersection rule.
JimBobSquarePants Feb 17, 2026
ce69978
Blaze style works.
JimBobSquarePants Feb 18, 2026
2cf5aea
Use less memory
JimBobSquarePants Feb 18, 2026
815b1e6
Use nint
JimBobSquarePants Feb 18, 2026
ed7c042
Remove old scanner/rasterizer
JimBobSquarePants Feb 18, 2026
4df8f1a
Document
JimBobSquarePants Feb 18, 2026
1714a6e
Precompute fixed values.
JimBobSquarePants Feb 18, 2026
c852e15
Add single tile hot path.
JimBobSquarePants Feb 18, 2026
38e9d2d
Better IDrawingBackend
JimBobSquarePants Feb 18, 2026
48b4236
Update ClippedShapeGenerator.cs
JimBobSquarePants Feb 18, 2026
8c84666
Update Issue_330.cs
JimBobSquarePants Feb 18, 2026
35acddc
Remove project references
JimBobSquarePants Feb 19, 2026
f1d51f9
Update reference images to match new rasterizer
JimBobSquarePants Feb 19, 2026
7a983d3
Update build pipeline
JimBobSquarePants Feb 19, 2026
cc44415
Update DrawShapesWithImageSharp.csproj
JimBobSquarePants Feb 19, 2026
3b457fb
Fix mac build
JimBobSquarePants Feb 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/ImageSharp.Drawing/ImageSharp.Drawing.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
<ItemGroup>
<PackageReference Include="SixLabors.Fonts" Version="3.0.0-alpha.0.1" />
<PackageReference Include="SixLabors.ImageSharp" Version="4.0.0-alpha.0.44" />
<PackageReference Include="SixLabors.PolygonClipper" Version="1.0.0-alpha.0.48" />
</ItemGroup>
<Import Project="..\..\shared-infrastructure\src\SharedInfrastructure\SharedInfrastructure.projitems" Label="Shared" />
</Project>
6 changes: 4 additions & 2 deletions src/ImageSharp.Drawing/Processing/ShapeOptions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.

using SixLabors.PolygonClipper;

namespace SixLabors.ImageSharp.Drawing.Processing;

/// <summary>
Expand All @@ -24,9 +26,9 @@ private ShapeOptions(ShapeOptions source)
/// <summary>
/// Gets or sets the clipping operation.
/// <para/>
/// Defaults to <see cref="ClippingOperation.Difference"/>.
/// Defaults to <see cref="BooleanOperation.Difference"/>.
/// </summary>
public ClippingOperation ClippingOperation { get; set; } = ClippingOperation.Difference;
public BooleanOperation ClippingOperation { get; set; } = BooleanOperation.Difference;
Comment thread
stefannikolei marked this conversation as resolved.
Outdated

/// <summary>
/// Gets or sets the rule for calculating intersection points.
Expand Down
2 changes: 1 addition & 1 deletion src/ImageSharp.Drawing/Shapes/ClipPathExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public static IPath Clip(
clipper.AddPath(subjectPath, ClippingType.Subject);
clipper.AddPaths(clipPaths, ClippingType.Clip);

IPath[] result = clipper.GenerateClippedShapes(options.ClippingOperation, options.IntersectionRule);
IPath[] result = clipper.GenerateClippedShapes(options.ClippingOperation);

return new ComplexPolygon(result);
}
Expand Down
38 changes: 0 additions & 38 deletions src/ImageSharp.Drawing/Shapes/ClippingOperation.cs

This file was deleted.

68 changes: 34 additions & 34 deletions src/ImageSharp.Drawing/Shapes/PolygonClipper/Clipper.cs
Original file line number Diff line number Diff line change
@@ -1,59 +1,46 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.

using SixLabors.PolygonClipper;

namespace SixLabors.ImageSharp.Drawing.Shapes.PolygonClipper;

/// <summary>
/// Library to clip polygons.
/// </summary>
internal class Clipper
{
private readonly PolygonClipper polygonClipper;

/// <summary>
/// Initializes a new instance of the <see cref="Clipper"/> class.
/// </summary>
public Clipper()
=> this.polygonClipper = new PolygonClipper();
private SixLabors.PolygonClipper.Polygon? subject;
private SixLabors.PolygonClipper.Polygon? clip;

/// <summary>
/// Generates the clipped shapes from the previously provided paths.
/// </summary>
/// <param name="operation">The clipping operation.</param>
/// <param name="rule">The intersection rule.</param>

Check failure on line 20 in src/ImageSharp.Drawing/Shapes/PolygonClipper/Clipper.cs

View workflow job for this annotation

GitHub Actions / Build (false, macos-13, net9.0, 9.0.x, true, -x64, false)

Check failure on line 20 in src/ImageSharp.Drawing/Shapes/PolygonClipper/Clipper.cs

View workflow job for this annotation

GitHub Actions / Build (false, macos-13, net9.0, 9.0.x, true, -x64, false)

XML comment has a param tag for 'rule', but there is no parameter by that name

Check failure on line 20 in src/ImageSharp.Drawing/Shapes/PolygonClipper/Clipper.cs

View workflow job for this annotation

GitHub Actions / Build (false, macos-13, net9.0, 9.0.x, true, -x64, false)

Check failure on line 20 in src/ImageSharp.Drawing/Shapes/PolygonClipper/Clipper.cs

View workflow job for this annotation

GitHub Actions / Build (false, macos-13, net9.0, 9.0.x, true, -x64, false)

XML comment has a param tag for 'rule', but there is no parameter by that name
/// <returns>The <see cref="T:IPath[]"/>.</returns>
public IPath[] GenerateClippedShapes(ClippingOperation operation, IntersectionRule rule)
public IPath[] GenerateClippedShapes(BooleanOperation operation)
{
PathsF closedPaths = [];
PathsF openPaths = [];
ArgumentNullException.ThrowIfNull(this.subject);
ArgumentNullException.ThrowIfNull(this.clip);

FillRule fillRule = rule == IntersectionRule.EvenOdd ? FillRule.EvenOdd : FillRule.NonZero;
this.polygonClipper.Execute(operation, fillRule, closedPaths, openPaths);
SixLabors.PolygonClipper.PolygonClipper polygonClipper = new(this.subject, this.clip, operation);

IPath[] shapes = new IPath[closedPaths.Count + openPaths.Count];
SixLabors.PolygonClipper.Polygon result = polygonClipper.Run();

Check failure on line 30 in src/ImageSharp.Drawing/Shapes/PolygonClipper/Clipper.cs

View workflow job for this annotation

GitHub Actions / Build (false, macos-13, net9.0, 9.0.x, true, -x64, false)

Check failure on line 30 in src/ImageSharp.Drawing/Shapes/PolygonClipper/Clipper.cs

View workflow job for this annotation

GitHub Actions / Build (false, macos-13, net9.0, 9.0.x, true, -x64, false)

int index = 0;
for (int i = 0; i < closedPaths.Count; i++)
{
PathF path = closedPaths[i];
PointF[] points = new PointF[path.Count];

for (int j = 0; j < path.Count; j++)
{
points[j] = path[j];
}
IPath[] shapes = new IPath[result.Count];

shapes[index++] = new Polygon(points);
}

for (int i = 0; i < openPaths.Count; i++)
int index = 0;
for (int i = 0; i < result.Count; i++)
{
PathF path = openPaths[i];
PointF[] points = new PointF[path.Count];
Contour contour = result[i];
PointF[] points = new PointF[contour.Count];

for (int j = 0; j < path.Count; j++)
for (int j = 0; j < contour.Count; j++)
{
points[j] = path[j];
Vertex vertex = contour[j];
points[j] = new PointF((float)vertex.X, (float)vertex.Y);
}

shapes[index++] = new Polygon(points);
Expand Down Expand Up @@ -100,12 +87,25 @@
internal void AddPath(ISimplePath path, ClippingType clippingType)
{
ReadOnlySpan<PointF> vectors = path.Points.Span;
PathF points = new(vectors.Length);
for (int i = 0; i < vectors.Length; i++)
SixLabors.PolygonClipper.Polygon polygon = [];
Contour contour = new();
polygon.Add(contour);

foreach (PointF point in vectors)
{
points.Add(vectors[i]);
contour.AddVertex(new Vertex(point.X, point.Y));
}

this.polygonClipper.AddPath(points, clippingType, !path.IsClosed);
switch (clippingType)
{
case ClippingType.Clip:
this.clip = polygon;
break;
case ClippingType.Subject:
this.subject = polygon;
break;
default:
throw new ArgumentOutOfRangeException(nameof(clippingType), clippingType, null);
}
}
}
Loading
Loading